4 #include "bformatdec.h"
6 #include "mixer_defs.h"
13 typedef struct BandSplitter
{
20 static void bandsplit_init(BandSplitter
*splitter
, ALfloat freq_mult
)
22 ALfloat w
= freq_mult
* F_TAU
;
25 splitter
->coeff
= (sinf(w
) - 1.0f
) / cw
;
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
)
41 coeff
= splitter
->coeff
*0.5f
+ 0.5f
;
44 for(i
= 0;i
< count
;i
++)
61 coeff
= splitter
->coeff
;
63 for(i
= 0;i
< count
;i
++)
71 hpout
[i
] = x
- lpout
[i
];
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) */
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 CubePoints
[8][3] = {
134 { -0.577350269f
, 0.577350269f
, -0.577350269f
},
135 { 0.577350269f
, 0.577350269f
, -0.577350269f
},
136 { -0.577350269f
, 0.577350269f
, 0.577350269f
},
137 { 0.577350269f
, 0.577350269f
, 0.577350269f
},
138 { -0.577350269f
, -0.577350269f
, -0.577350269f
},
139 { 0.577350269f
, -0.577350269f
, -0.577350269f
},
140 { -0.577350269f
, -0.577350269f
, 0.577350269f
},
141 { 0.577350269f
, -0.577350269f
, 0.577350269f
},
143 static const ALfloat CubeMatrix
[8][FB_Max
][MAX_AMBI_COEFFS
] = {
144 { { 0.25f
, 0.14425f
, 0.14425f
, 0.14425f
}, { 0.125f
, 0.125f
, 0.125f
, 0.125f
} },
145 { { 0.25f
, -0.14425f
, 0.14425f
, 0.14425f
}, { 0.125f
, -0.125f
, 0.125f
, 0.125f
} },
146 { { 0.25f
, 0.14425f
, 0.14425f
, -0.14425f
}, { 0.125f
, 0.125f
, 0.125f
, -0.125f
} },
147 { { 0.25f
, -0.14425f
, 0.14425f
, -0.14425f
}, { 0.125f
, -0.125f
, 0.125f
, -0.125f
} },
148 { { 0.25f
, 0.14425f
, -0.14425f
, 0.14425f
}, { 0.125f
, 0.125f
, -0.125f
, 0.125f
} },
149 { { 0.25f
, -0.14425f
, -0.14425f
, 0.14425f
}, { 0.125f
, -0.125f
, -0.125f
, 0.125f
} },
150 { { 0.25f
, 0.14425f
, -0.14425f
, -0.14425f
}, { 0.125f
, 0.125f
, -0.125f
, -0.125f
} },
151 { { 0.25f
, -0.14425f
, -0.14425f
, -0.14425f
}, { 0.125f
, -0.125f
, -0.125f
, -0.125f
} },
153 static ALfloat CubeEncoder
[8][MAX_AMBI_COEFFS
];
156 static inline MatrixMixerFunc
SelectMixer(void)
159 if((CPUCapFlags
&CPU_CAP_SSE
))
163 if((CPUCapFlags
&CPU_CAP_NEON
))
169 static MatrixMixerFunc MixMatrixRow
= MixRow_C
;
172 static alonce_flag bformatdec_inited
= AL_ONCE_FLAG_INIT
;
174 static void init_bformatdec(void)
178 MixMatrixRow
= SelectMixer();
180 for(i
= 0;i
< COUNTOF(CubePoints
);i
++)
181 CalcDirectionCoeffs(CubePoints
[i
], 0.0f
, CubeEncoder
[i
]);
183 CalcXYZCoeffs(-0.707106781f
, 0.0f
, -0.707106781f
, 0.0f
, SquareEncoder
[0]);
184 CalcXYZCoeffs( 0.707106781f
, 0.0f
, -0.707106781f
, 0.0f
, SquareEncoder
[1]);
185 CalcXYZCoeffs(-0.707106781f
, 0.0f
, 0.707106781f
, 0.0f
, SquareEncoder
[2]);
186 CalcXYZCoeffs( 0.707106781f
, 0.0f
, 0.707106781f
, 0.0f
, SquareEncoder
[3]);
190 /* Remove the skipped height-related coefficients for 2D rendering. */
191 SquareEncoder
[i
][2] = SquareEncoder
[i
][3];
192 SquareEncoder
[i
][3] = SquareEncoder
[i
][4];
193 SquareEncoder
[i
][4] = SquareEncoder
[i
][8];
194 SquareEncoder
[i
][5] = SquareEncoder
[i
][9];
195 SquareEncoder
[i
][6] = SquareEncoder
[i
][15];
196 for(j
= 7;j
< MAX_AMBI_COEFFS
;j
++)
197 SquareEncoder
[i
][j
] = 0.0f
;
202 #define MAX_DELAY_LENGTH 128
204 /* NOTE: BandSplitter filters are unused with single-band decoding */
205 typedef struct BFormatDec
{
206 ALboolean Enabled
[MAX_OUTPUT_CHANNELS
];
209 alignas(16) ALfloat Dual
[MAX_OUTPUT_CHANNELS
][FB_Max
][MAX_AMBI_COEFFS
];
210 alignas(16) ALfloat Single
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
213 BandSplitter XOver
[MAX_AMBI_COEFFS
];
215 ALfloat (*Samples
)[BUFFERSIZE
];
216 /* These two alias into Samples */
217 ALfloat (*SamplesHF
)[BUFFERSIZE
];
218 ALfloat (*SamplesLF
)[BUFFERSIZE
];
220 alignas(16) ALfloat ChannelMix
[BUFFERSIZE
];
223 alignas(16) ALfloat Buffer
[MAX_DELAY_LENGTH
];
224 ALuint Length
; /* Valid range is [0...MAX_DELAY_LENGTH). */
225 } Delay
[MAX_OUTPUT_CHANNELS
];
228 BandSplitter XOver
[4];
230 const ALfloat (*restrict Matrix
)[FB_Max
][MAX_AMBI_COEFFS
];
231 const ALfloat (*restrict Encoder
)[MAX_AMBI_COEFFS
];
237 ALboolean Periphonic
;
240 BFormatDec
*bformatdec_alloc()
242 alcall_once(&bformatdec_inited
, init_bformatdec
);
243 return al_calloc(16, sizeof(BFormatDec
));
246 void bformatdec_free(BFormatDec
*dec
)
250 al_free(dec
->Samples
);
252 dec
->SamplesHF
= NULL
;
253 dec
->SamplesLF
= NULL
;
255 memset(dec
, 0, sizeof(*dec
));
260 int bformatdec_getOrder(const struct BFormatDec
*dec
)
264 if(dec
->NumChannels
> 9) return 3;
265 if(dec
->NumChannels
> 4) return 2;
266 if(dec
->NumChannels
> 1) return 1;
270 if(dec
->NumChannels
> 5) return 3;
271 if(dec
->NumChannels
> 3) return 2;
272 if(dec
->NumChannels
> 1) return 1;
277 void bformatdec_reset(BFormatDec
*dec
, const AmbDecConf
*conf
, ALuint chancount
, ALuint srate
, const ALuint chanmap
[MAX_OUTPUT_CHANNELS
], int flags
)
279 static const ALuint map2DTo3D
[MAX_AMBI2D_COEFFS
] = {
282 const ALfloat
*coeff_scale
= UnitScale
;
283 ALfloat distgain
[MAX_OUTPUT_CHANNELS
];
284 ALfloat maxdist
, ratio
;
287 al_free(dec
->Samples
);
289 dec
->SamplesHF
= NULL
;
290 dec
->SamplesLF
= NULL
;
292 dec
->NumChannels
= chancount
;
293 dec
->Samples
= al_calloc(16, dec
->NumChannels
*2 * sizeof(dec
->Samples
[0]));
294 dec
->SamplesHF
= dec
->Samples
;
295 dec
->SamplesLF
= dec
->SamplesHF
+ dec
->NumChannels
;
297 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
298 dec
->Enabled
[i
] = AL_FALSE
;
299 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
300 dec
->Enabled
[chanmap
[i
]] = AL_TRUE
;
302 if(conf
->CoeffScale
== ADS_SN3D
)
303 coeff_scale
= SN3D2N3DScale
;
304 else if(conf
->CoeffScale
== ADS_FuMa
)
305 coeff_scale
= FuMa2N3DScale
;
307 ratio
= 400.0f
/ (ALfloat
)srate
;
309 bandsplit_init(&dec
->UpSampler
.XOver
[i
], ratio
);
310 if((conf
->ChanMask
&AMBI_PERIPHONIC_MASK
))
312 dec
->UpSampler
.Matrix
= CubeMatrix
;
313 dec
->UpSampler
.Encoder
= (const ALfloat(*)[MAX_AMBI_COEFFS
])CubeEncoder
;
314 dec
->UpSampler
.NumChannels
= 8;
315 dec
->Periphonic
= AL_TRUE
;
319 dec
->UpSampler
.Matrix
= SquareMatrix
;
320 dec
->UpSampler
.Encoder
= (const ALfloat(*)[MAX_AMBI_COEFFS
])SquareEncoder
;
321 dec
->UpSampler
.NumChannels
= 4;
322 dec
->Periphonic
= AL_FALSE
;
326 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
328 maxdist
= maxf(maxdist
, conf
->Speakers
[i
].Distance
);
332 memset(dec
->Delay
, 0, sizeof(dec
->Delay
));
333 if((flags
&BFDF_DistanceComp
) && maxdist
> 0.0f
)
335 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
337 ALuint chan
= chanmap
[i
];
340 /* Distance compensation only delays in steps of the sample rate.
341 * This is a bit less accurate since the delay time falls to the
342 * nearest sample time, but it's far simpler as it doesn't have to
343 * deal with phase offsets. This means at 48khz, for instance, the
344 * distance delay will be in steps of about 7 millimeters.
346 delay
= floorf((maxdist
-conf
->Speakers
[i
].Distance
) / SPEEDOFSOUNDMETRESPERSEC
*
347 (ALfloat
)srate
+ 0.5f
);
348 if(delay
>= (ALfloat
)MAX_DELAY_LENGTH
)
349 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
350 al_string_get_cstr(conf
->Speakers
[i
].Name
), delay
, MAX_DELAY_LENGTH
);
352 dec
->Delay
[chan
].Length
= (ALuint
)clampf(delay
, 0.0f
, (ALfloat
)(MAX_DELAY_LENGTH
-1));
353 distgain
[i
] = conf
->Speakers
[i
].Distance
/ maxdist
;
354 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan
,
355 al_string_get_cstr(conf
->Speakers
[i
].Name
), dec
->Delay
[chan
].Length
, distgain
[i
]
360 memset(&dec
->Matrix
, 0, sizeof(dec
->Matrix
));
361 if(conf
->FreqBands
== 1)
363 dec
->DualBand
= AL_FALSE
;
364 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
366 ALuint chan
= chanmap
[i
];
372 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
374 ALuint l
= map2DTo3D
[j
];
375 if(j
== 0) gain
= conf
->HFOrderGain
[0];
376 else if(j
== 1) gain
= conf
->HFOrderGain
[1];
377 else if(j
== 3) gain
= conf
->HFOrderGain
[2];
378 else if(j
== 5) gain
= conf
->HFOrderGain
[3];
379 if((conf
->ChanMask
&(1<<l
)))
380 dec
->Matrix
.Single
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[l
] *
386 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
388 if(j
== 0) gain
= conf
->HFOrderGain
[0];
389 else if(j
== 1) gain
= conf
->HFOrderGain
[1];
390 else if(j
== 4) gain
= conf
->HFOrderGain
[2];
391 else if(j
== 9) gain
= conf
->HFOrderGain
[3];
392 if((conf
->ChanMask
&(1<<j
)))
393 dec
->Matrix
.Single
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[j
] *
401 dec
->DualBand
= AL_TRUE
;
403 ratio
= conf
->XOverFreq
/ (ALfloat
)srate
;
404 for(i
= 0;i
< MAX_AMBI_COEFFS
;i
++)
405 bandsplit_init(&dec
->XOver
[i
], ratio
);
407 ratio
= powf(10.0f
, conf
->XOverRatio
/ 40.0f
);
408 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
410 ALuint chan
= chanmap
[i
];
416 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
418 ALuint l
= map2DTo3D
[j
];
419 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
420 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
421 else if(j
== 3) gain
= conf
->HFOrderGain
[2] * ratio
;
422 else if(j
== 5) gain
= conf
->HFOrderGain
[3] * ratio
;
423 if((conf
->ChanMask
&(1<<l
)))
424 dec
->Matrix
.Dual
[chan
][FB_HighFreq
][j
] = conf
->HFMatrix
[i
][k
++] /
425 coeff_scale
[l
] * gain
*
428 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
430 ALuint l
= map2DTo3D
[j
];
431 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
432 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
433 else if(j
== 3) gain
= conf
->LFOrderGain
[2] / ratio
;
434 else if(j
== 5) gain
= conf
->LFOrderGain
[3] / ratio
;
435 if((conf
->ChanMask
&(1<<l
)))
436 dec
->Matrix
.Dual
[chan
][FB_LowFreq
][j
] = conf
->LFMatrix
[i
][k
++] /
437 coeff_scale
[l
] * gain
*
443 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
445 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
446 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
447 else if(j
== 4) gain
= conf
->HFOrderGain
[2] * ratio
;
448 else if(j
== 9) gain
= conf
->HFOrderGain
[3] * ratio
;
449 if((conf
->ChanMask
&(1<<j
)))
450 dec
->Matrix
.Dual
[chan
][FB_HighFreq
][j
] = conf
->HFMatrix
[i
][k
++] /
451 coeff_scale
[j
] * gain
*
454 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
456 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
457 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
458 else if(j
== 4) gain
= conf
->LFOrderGain
[2] / ratio
;
459 else if(j
== 9) gain
= conf
->LFOrderGain
[3] / ratio
;
460 if((conf
->ChanMask
&(1<<j
)))
461 dec
->Matrix
.Dual
[chan
][FB_LowFreq
][j
] = conf
->LFMatrix
[i
][k
++] /
462 coeff_scale
[j
] * gain
*
471 void bformatdec_process(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
477 for(i
= 0;i
< dec
->NumChannels
;i
++)
478 bandsplit_process(&dec
->XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
479 InSamples
[i
], SamplesToDo
);
481 for(chan
= 0;chan
< OutChannels
;chan
++)
483 if(!dec
->Enabled
[chan
])
486 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
487 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Dual
[chan
][FB_HighFreq
],
488 dec
->SamplesHF
, dec
->NumChannels
, SamplesToDo
490 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Dual
[chan
][FB_LowFreq
],
491 dec
->SamplesLF
, dec
->NumChannels
, SamplesToDo
494 if(dec
->Delay
[chan
].Length
> 0)
496 const ALuint base
= dec
->Delay
[chan
].Length
;
497 if(SamplesToDo
>= base
)
499 for(i
= 0;i
< base
;i
++)
500 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
501 for(;i
< SamplesToDo
;i
++)
502 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
503 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
504 base
*sizeof(ALfloat
));
508 for(i
= 0;i
< SamplesToDo
;i
++)
509 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
510 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
512 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
513 SamplesToDo
*sizeof(ALfloat
));
516 else for(i
= 0;i
< SamplesToDo
;i
++)
517 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
522 for(chan
= 0;chan
< OutChannels
;chan
++)
524 if(!dec
->Enabled
[chan
])
527 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
528 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Single
[chan
], InSamples
,
529 dec
->NumChannels
, SamplesToDo
);
531 if(dec
->Delay
[chan
].Length
> 0)
533 const ALuint base
= dec
->Delay
[chan
].Length
;
534 if(SamplesToDo
>= base
)
536 for(i
= 0;i
< base
;i
++)
537 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
538 for(;i
< SamplesToDo
;i
++)
539 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
540 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
541 base
*sizeof(ALfloat
));
545 for(i
= 0;i
< SamplesToDo
;i
++)
546 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
547 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
549 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
550 SamplesToDo
*sizeof(ALfloat
));
553 else for(i
= 0;i
< SamplesToDo
;i
++)
554 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
560 void bformatdec_upSample(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint InChannels
, ALuint SamplesToDo
)
564 /* First, split the first-order components into low and high frequency
565 * bands. This assumes SamplesHF and SamplesLF have enough space for first-
566 * order content (to which, this up-sampler is only used with second-order
567 * or higher decoding, so it will).
569 for(i
= 0;i
< InChannels
;i
++)
570 bandsplit_process(&dec
->UpSampler
.XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
571 InSamples
[i
], SamplesToDo
);
573 /* This up-sampler is very simplistic. It essentially decodes the first-
574 * order content to a square channel array (or cube if height is desired),
575 * then encodes those points onto the higher order soundfield.
577 for(k
= 0;k
< dec
->UpSampler
.NumChannels
;k
++)
579 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
580 MixMatrixRow(dec
->ChannelMix
, dec
->UpSampler
.Matrix
[k
][FB_HighFreq
],
581 dec
->SamplesHF
, InChannels
, SamplesToDo
);
582 MixMatrixRow(dec
->ChannelMix
, dec
->UpSampler
.Matrix
[k
][FB_LowFreq
],
583 dec
->SamplesLF
, InChannels
, SamplesToDo
);
585 for(j
= 0;j
< dec
->NumChannels
;j
++)
587 ALfloat gain
= dec
->UpSampler
.Encoder
[k
][j
];
588 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
590 for(i
= 0;i
< SamplesToDo
;i
++)
591 OutBuffer
[j
][i
] += dec
->ChannelMix
[i
] * gain
;
597 typedef struct AmbiUpsampler
{
598 alignas(16) ALfloat SamplesHF
[4][BUFFERSIZE
];
599 alignas(16) ALfloat SamplesLF
[4][BUFFERSIZE
];
601 alignas(16) ALfloat ChannelMix
[BUFFERSIZE
];
603 BandSplitter XOver
[4];
605 ALfloat Gains
[8][MAX_OUTPUT_CHANNELS
];
609 AmbiUpsampler
*ambiup_alloc()
611 alcall_once(&bformatdec_inited
, init_bformatdec
);
612 return al_calloc(16, sizeof(AmbiUpsampler
));
615 void ambiup_free(struct AmbiUpsampler
*ambiup
)
620 void ambiup_reset(struct AmbiUpsampler
*ambiup
, const ALCdevice
*device
)
625 ratio
= 400.0f
/ (ALfloat
)device
->Frequency
;
627 bandsplit_init(&ambiup
->XOver
[i
], ratio
);
629 ambiup
->NumChannels
= COUNTOF(CubePoints
);
630 for(i
= 0;i
< ambiup
->NumChannels
;i
++)
631 ComputePanningGains(device
->Dry
, CubeEncoder
[i
], 1.0f
, ambiup
->Gains
[i
]);
634 void ambiup_process(struct AmbiUpsampler
*ambiup
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
639 bandsplit_process(&ambiup
->XOver
[i
], ambiup
->SamplesHF
[i
], ambiup
->SamplesLF
[i
],
640 InSamples
[i
], SamplesToDo
);
642 for(k
= 0;k
< ambiup
->NumChannels
;k
++)
644 memset(ambiup
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
645 MixMatrixRow(ambiup
->ChannelMix
, CubeMatrix
[k
][FB_HighFreq
],
646 ambiup
->SamplesHF
, 4, SamplesToDo
);
647 MixMatrixRow(ambiup
->ChannelMix
, CubeMatrix
[k
][FB_LowFreq
],
648 ambiup
->SamplesLF
, 4, SamplesToDo
);
650 for(j
= 0;j
< OutChannels
;j
++)
652 ALfloat gain
= ambiup
->Gains
[k
][j
];
653 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
655 for(i
= 0;i
< SamplesToDo
;i
++)
656 OutBuffer
[j
][i
] += ambiup
->ChannelMix
[i
] * gain
;