Recognize Headset formfactors as headphones
[openal-soft.git] / Alc / bformatdec.c
blob0722c061fa5b830e36ea0f6dda27e9679055f404
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 Ambi2DEncoder[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 Ambi3DEncoder[8][MAX_AMBI_COEFFS];
164 static inline RowMixerFunc SelectRowMixer(void)
166 #ifdef HAVE_SSE
167 if((CPUCapFlags&CPU_CAP_SSE))
168 return MixRow_SSE;
169 #endif
170 #ifdef HAVE_NEON
171 if((CPUCapFlags&CPU_CAP_NEON))
172 return MixRow_Neon;
173 #endif
174 return MixRow_C;
177 static RowMixerFunc MixMatrixRow = MixRow_C;
180 static alonce_flag bformatdec_inited = AL_ONCE_FLAG_INIT;
182 static void init_bformatdec(void)
184 ALuint i, j;
186 MixMatrixRow = SelectRowMixer();
188 for(i = 0;i < COUNTOF(Ambi3DPoints);i++)
189 CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, Ambi3DEncoder[i]);
191 for(i = 0;i < COUNTOF(Ambi2DPoints);i++)
193 CalcDirectionCoeffs(Ambi2DPoints[i], 0.0f, Ambi2DEncoder[i]);
195 /* Remove the skipped height-related coefficients for 2D rendering. */
196 Ambi2DEncoder[i][2] = Ambi2DEncoder[i][3];
197 Ambi2DEncoder[i][3] = Ambi2DEncoder[i][4];
198 Ambi2DEncoder[i][4] = Ambi2DEncoder[i][8];
199 Ambi2DEncoder[i][5] = Ambi2DEncoder[i][9];
200 Ambi2DEncoder[i][6] = Ambi2DEncoder[i][15];
201 for(j = 7;j < MAX_AMBI_COEFFS;j++)
202 Ambi2DEncoder[i][j] = 0.0f;
207 #define MAX_DELAY_LENGTH 128
209 /* NOTE: BandSplitter filters are unused with single-band decoding */
210 typedef struct BFormatDec {
211 ALboolean Enabled[MAX_OUTPUT_CHANNELS];
213 union {
214 alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][FB_Max][MAX_AMBI_COEFFS];
215 alignas(16) ALfloat Single[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
216 } Matrix;
218 BandSplitter XOver[MAX_AMBI_COEFFS];
220 ALfloat (*Samples)[BUFFERSIZE];
221 /* These two alias into Samples */
222 ALfloat (*SamplesHF)[BUFFERSIZE];
223 ALfloat (*SamplesLF)[BUFFERSIZE];
225 alignas(16) ALfloat ChannelMix[BUFFERSIZE];
227 struct {
228 alignas(16) ALfloat Buffer[MAX_DELAY_LENGTH];
229 ALuint Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
230 } Delay[MAX_OUTPUT_CHANNELS];
232 struct {
233 BandSplitter XOver[4];
235 ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max];
236 } UpSampler;
238 ALuint NumChannels;
239 ALboolean DualBand;
240 ALboolean Periphonic;
241 } BFormatDec;
243 BFormatDec *bformatdec_alloc()
245 alcall_once(&bformatdec_inited, init_bformatdec);
246 return al_calloc(16, sizeof(BFormatDec));
249 void bformatdec_free(BFormatDec *dec)
251 if(dec)
253 al_free(dec->Samples);
254 dec->Samples = NULL;
255 dec->SamplesHF = NULL;
256 dec->SamplesLF = NULL;
258 memset(dec, 0, sizeof(*dec));
259 al_free(dec);
263 int bformatdec_getOrder(const struct BFormatDec *dec)
265 if(dec->Periphonic)
267 if(dec->NumChannels > 9) return 3;
268 if(dec->NumChannels > 4) return 2;
269 if(dec->NumChannels > 1) return 1;
271 else
273 if(dec->NumChannels > 5) return 3;
274 if(dec->NumChannels > 3) return 2;
275 if(dec->NumChannels > 1) return 1;
277 return 0;
280 void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS], int flags)
282 static const ALuint map2DTo3D[MAX_AMBI2D_COEFFS] = {
283 0, 1, 3, 4, 8, 9, 15
285 const ALfloat *coeff_scale = UnitScale;
286 ALfloat distgain[MAX_OUTPUT_CHANNELS];
287 ALfloat maxdist, ratio;
288 ALuint i, j, k;
290 al_free(dec->Samples);
291 dec->Samples = NULL;
292 dec->SamplesHF = NULL;
293 dec->SamplesLF = NULL;
295 dec->NumChannels = chancount;
296 dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0]));
297 dec->SamplesHF = dec->Samples;
298 dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
300 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
301 dec->Enabled[i] = AL_FALSE;
302 for(i = 0;i < conf->NumSpeakers;i++)
303 dec->Enabled[chanmap[i]] = AL_TRUE;
305 if(conf->CoeffScale == ADS_SN3D)
306 coeff_scale = SN3D2N3DScale;
307 else if(conf->CoeffScale == ADS_FuMa)
308 coeff_scale = FuMa2N3DScale;
310 ratio = 400.0f / (ALfloat)srate;
311 for(i = 0;i < 4;i++)
312 bandsplit_init(&dec->UpSampler.XOver[i], ratio);
313 memset(dec->UpSampler.Gains, 0, sizeof(dec->UpSampler.Gains));
314 if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
316 /* Combine the matrices that do the in->virt and virt->out conversions
317 * so we get a single in->out conversion.
319 for(i = 0;i < 4;i++)
321 for(j = 0;j < dec->NumChannels;j++)
323 ALfloat *gains = dec->UpSampler.Gains[i][j];
324 for(k = 0;k < COUNTOF(Ambi3DDecoder);k++)
326 gains[FB_HighFreq] += Ambi3DDecoder[k][FB_HighFreq][i]*Ambi3DEncoder[k][j];
327 gains[FB_LowFreq] += Ambi3DDecoder[k][FB_LowFreq][i]*Ambi3DEncoder[k][j];
332 dec->Periphonic = AL_TRUE;
334 else
336 for(i = 0;i < 4;i++)
338 for(j = 0;j < dec->NumChannels;j++)
340 ALfloat *gains = dec->UpSampler.Gains[i][j];
341 for(k = 0;k < COUNTOF(Ambi2DDecoder);k++)
343 gains[FB_HighFreq] += Ambi2DDecoder[k][FB_HighFreq][i]*Ambi2DEncoder[k][j];
344 gains[FB_LowFreq] += Ambi2DDecoder[k][FB_LowFreq][i]*Ambi2DEncoder[k][j];
349 dec->Periphonic = AL_FALSE;
352 maxdist = 0.0f;
353 for(i = 0;i < conf->NumSpeakers;i++)
355 maxdist = maxf(maxdist, conf->Speakers[i].Distance);
356 distgain[i] = 1.0f;
359 memset(dec->Delay, 0, sizeof(dec->Delay));
360 if((flags&BFDF_DistanceComp) && maxdist > 0.0f)
362 for(i = 0;i < conf->NumSpeakers;i++)
364 ALuint chan = chanmap[i];
365 ALfloat delay;
367 /* Distance compensation only delays in steps of the sample rate.
368 * This is a bit less accurate since the delay time falls to the
369 * nearest sample time, but it's far simpler as it doesn't have to
370 * deal with phase offsets. This means at 48khz, for instance, the
371 * distance delay will be in steps of about 7 millimeters.
373 delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
374 (ALfloat)srate + 0.5f);
375 if(delay >= (ALfloat)MAX_DELAY_LENGTH)
376 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
377 al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
379 dec->Delay[chan].Length = (ALuint)clampf(delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1));
380 distgain[i] = conf->Speakers[i].Distance / maxdist;
381 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan,
382 al_string_get_cstr(conf->Speakers[i].Name), dec->Delay[chan].Length, distgain[i]
387 memset(&dec->Matrix, 0, sizeof(dec->Matrix));
388 if(conf->FreqBands == 1)
390 dec->DualBand = AL_FALSE;
391 for(i = 0;i < conf->NumSpeakers;i++)
393 ALuint chan = chanmap[i];
394 ALfloat gain;
395 ALuint j, k;
397 if(!dec->Periphonic)
399 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
401 ALuint l = map2DTo3D[j];
402 if(j == 0) gain = conf->HFOrderGain[0];
403 else if(j == 1) gain = conf->HFOrderGain[1];
404 else if(j == 3) gain = conf->HFOrderGain[2];
405 else if(j == 5) gain = conf->HFOrderGain[3];
406 if((conf->ChanMask&(1<<l)))
407 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] *
408 gain * distgain[i];
411 else
413 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
415 if(j == 0) gain = conf->HFOrderGain[0];
416 else if(j == 1) gain = conf->HFOrderGain[1];
417 else if(j == 4) gain = conf->HFOrderGain[2];
418 else if(j == 9) gain = conf->HFOrderGain[3];
419 if((conf->ChanMask&(1<<j)))
420 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] *
421 gain * distgain[i];
426 else
428 dec->DualBand = AL_TRUE;
430 ratio = conf->XOverFreq / (ALfloat)srate;
431 for(i = 0;i < MAX_AMBI_COEFFS;i++)
432 bandsplit_init(&dec->XOver[i], ratio);
434 ratio = powf(10.0f, conf->XOverRatio / 40.0f);
435 for(i = 0;i < conf->NumSpeakers;i++)
437 ALuint chan = chanmap[i];
438 ALfloat gain;
439 ALuint j, k;
441 if(!dec->Periphonic)
443 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
445 ALuint l = map2DTo3D[j];
446 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
447 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
448 else if(j == 3) gain = conf->HFOrderGain[2] * ratio;
449 else if(j == 5) gain = conf->HFOrderGain[3] * ratio;
450 if((conf->ChanMask&(1<<l)))
451 dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
452 coeff_scale[l] * gain *
453 distgain[i];
455 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
457 ALuint l = map2DTo3D[j];
458 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
459 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
460 else if(j == 3) gain = conf->LFOrderGain[2] / ratio;
461 else if(j == 5) gain = conf->LFOrderGain[3] / ratio;
462 if((conf->ChanMask&(1<<l)))
463 dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
464 coeff_scale[l] * gain *
465 distgain[i];
468 else
470 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
472 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
473 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
474 else if(j == 4) gain = conf->HFOrderGain[2] * ratio;
475 else if(j == 9) gain = conf->HFOrderGain[3] * ratio;
476 if((conf->ChanMask&(1<<j)))
477 dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
478 coeff_scale[j] * gain *
479 distgain[i];
481 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
483 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
484 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
485 else if(j == 4) gain = conf->LFOrderGain[2] / ratio;
486 else if(j == 9) gain = conf->LFOrderGain[3] / ratio;
487 if((conf->ChanMask&(1<<j)))
488 dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
489 coeff_scale[j] * gain *
490 distgain[i];
498 void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo)
500 ALuint chan, i;
502 if(dec->DualBand)
504 for(i = 0;i < dec->NumChannels;i++)
505 bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
506 InSamples[i], SamplesToDo);
508 for(chan = 0;chan < OutChannels;chan++)
510 if(!dec->Enabled[chan])
511 continue;
513 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
514 MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_HighFreq],
515 dec->SamplesHF, dec->NumChannels, SamplesToDo
517 MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_LowFreq],
518 dec->SamplesLF, dec->NumChannels, SamplesToDo
521 if(dec->Delay[chan].Length > 0)
523 const ALuint base = dec->Delay[chan].Length;
524 if(SamplesToDo >= base)
526 for(i = 0;i < base;i++)
527 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
528 for(;i < SamplesToDo;i++)
529 OutBuffer[chan][i] += dec->ChannelMix[i-base];
530 memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base],
531 base*sizeof(ALfloat));
533 else
535 for(i = 0;i < SamplesToDo;i++)
536 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
537 memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo,
538 base - SamplesToDo);
539 memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix,
540 SamplesToDo*sizeof(ALfloat));
543 else for(i = 0;i < SamplesToDo;i++)
544 OutBuffer[chan][i] += dec->ChannelMix[i];
547 else
549 for(chan = 0;chan < OutChannels;chan++)
551 if(!dec->Enabled[chan])
552 continue;
554 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
555 MixMatrixRow(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
556 dec->NumChannels, SamplesToDo);
558 if(dec->Delay[chan].Length > 0)
560 const ALuint base = dec->Delay[chan].Length;
561 if(SamplesToDo >= base)
563 for(i = 0;i < base;i++)
564 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
565 for(;i < SamplesToDo;i++)
566 OutBuffer[chan][i] += dec->ChannelMix[i-base];
567 memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base],
568 base*sizeof(ALfloat));
570 else
572 for(i = 0;i < SamplesToDo;i++)
573 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
574 memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo,
575 base - SamplesToDo);
576 memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix,
577 SamplesToDo*sizeof(ALfloat));
580 else for(i = 0;i < SamplesToDo;i++)
581 OutBuffer[chan][i] += dec->ChannelMix[i];
587 void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint InChannels, ALuint SamplesToDo)
589 ALuint i, j;
591 /* This up-sampler is very simplistic. It essentially decodes the first-
592 * order content to a square channel array (or cube if height is desired),
593 * then encodes those points onto the higher order soundfield. The decoder
594 * and encoder matrices have been combined to directly convert each input
595 * channel to the output, without the need for storing the virtual channel
596 * array.
598 for(i = 0;i < InChannels;i++)
600 /* First, split the first-order components into low and high frequency
601 * bands.
603 bandsplit_process(&dec->UpSampler.XOver[i],
604 dec->Samples[FB_HighFreq], dec->Samples[FB_LowFreq],
605 InSamples[i], SamplesToDo
608 /* Now write each band to the output. */
609 for(j = 0;j < dec->NumChannels;j++)
610 MixMatrixRow(OutBuffer[j], dec->UpSampler.Gains[i][j],
611 dec->Samples, FB_Max, SamplesToDo);
616 typedef struct AmbiUpsampler {
617 alignas(16) ALfloat Samples[FB_Max][BUFFERSIZE];
619 BandSplitter XOver[4];
621 ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max];
622 } AmbiUpsampler;
624 AmbiUpsampler *ambiup_alloc()
626 alcall_once(&bformatdec_inited, init_bformatdec);
627 return al_calloc(16, sizeof(AmbiUpsampler));
630 void ambiup_free(struct AmbiUpsampler *ambiup)
632 al_free(ambiup);
635 void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device)
637 ALfloat gains[8][MAX_OUTPUT_CHANNELS];
638 ALfloat ratio;
639 ALuint i, j, k;
641 ratio = 400.0f / (ALfloat)device->Frequency;
642 for(i = 0;i < 4;i++)
643 bandsplit_init(&ambiup->XOver[i], ratio);
645 for(i = 0;i < COUNTOF(Ambi3DEncoder);i++)
646 ComputePanningGains(device->Dry, Ambi3DEncoder[i], 1.0f, gains[i]);
648 memset(ambiup->Gains, 0, sizeof(ambiup->Gains));
649 for(i = 0;i < 4;i++)
651 for(j = 0;j < device->Dry.NumChannels;j++)
653 for(k = 0;k < COUNTOF(Ambi3DDecoder);k++)
655 ambiup->Gains[i][j][FB_HighFreq] += Ambi3DDecoder[k][FB_HighFreq][i]*gains[k][j];
656 ambiup->Gains[i][j][FB_LowFreq] += Ambi3DDecoder[k][FB_LowFreq][i]*gains[k][j];
662 void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo)
664 ALuint i, j;
666 for(i = 0;i < 4;i++)
668 bandsplit_process(&ambiup->XOver[i],
669 ambiup->Samples[FB_HighFreq], ambiup->Samples[FB_LowFreq],
670 InSamples[i], SamplesToDo
673 for(j = 0;j < OutChannels;j++)
674 MixMatrixRow(OutBuffer[j], ambiup->Gains[i][j],
675 ambiup->Samples, FB_Max, SamplesToDo);