4 #include "bformatdec.h"
12 typedef struct BandSplitter
{
19 static void bandsplit_init(BandSplitter
*splitter
, ALfloat freq_mult
)
21 ALfloat w
= freq_mult
* F_TAU
;
24 splitter
->coeff
= (sinf(w
) - 1.0f
) / cw
;
26 splitter
->coeff
= cw
* -0.5f
;
28 splitter
->lp_z1
= 0.0f
;
29 splitter
->lp_z2
= 0.0f
;
30 splitter
->hp_z1
= 0.0f
;
33 static void bandsplit_process(BandSplitter
*splitter
, ALfloat
*restrict hpout
, ALfloat
*restrict lpout
,
34 const ALfloat
*input
, ALuint count
)
39 coeff
= splitter
->coeff
*0.5f
+ 0.5f
;
40 for(i
= 0;i
< count
;i
++)
44 d
= (x
- splitter
->lp_z1
) * coeff
;
45 x
= splitter
->lp_z1
+ d
;
46 splitter
->lp_z1
= x
+ d
;
48 d
= (x
- splitter
->lp_z2
) * coeff
;
49 x
= splitter
->lp_z2
+ d
;
50 splitter
->lp_z2
= x
+ d
;
55 coeff
= splitter
->coeff
;
56 for(i
= 0;i
< count
;i
++)
60 d
= x
- coeff
*splitter
->hp_z1
;
61 x
= splitter
->hp_z1
+ coeff
*d
;
64 hpout
[i
] = x
- lpout
[i
];
69 static const ALfloat UnitScale
[MAX_AMBI_COEFFS
] = {
70 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
,
71 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
73 static const ALfloat SN3D2N3DScale
[MAX_AMBI_COEFFS
] = {
74 1.000000000f
, /* ACN 0 (W), sqrt(1) */
75 1.732050808f
, /* ACN 1 (Y), sqrt(3) */
76 1.732050808f
, /* ACN 2 (Z), sqrt(3) */
77 1.732050808f
, /* ACN 3 (X), sqrt(3) */
78 2.236067978f
, /* ACN 4 (V), sqrt(5) */
79 2.236067978f
, /* ACN 5 (T), sqrt(5) */
80 2.236067978f
, /* ACN 6 (R), sqrt(5) */
81 2.236067978f
, /* ACN 7 (S), sqrt(5) */
82 2.236067978f
, /* ACN 8 (U), sqrt(5) */
83 2.645751311f
, /* ACN 9 (Q), sqrt(7) */
84 2.645751311f
, /* ACN 10 (O), sqrt(7) */
85 2.645751311f
, /* ACN 11 (M), sqrt(7) */
86 2.645751311f
, /* ACN 12 (K), sqrt(7) */
87 2.645751311f
, /* ACN 13 (L), sqrt(7) */
88 2.645751311f
, /* ACN 14 (N), sqrt(7) */
89 2.645751311f
, /* ACN 15 (P), sqrt(7) */
91 static const ALfloat FuMa2N3DScale
[MAX_AMBI_COEFFS
] = {
92 1.414213562f
, /* ACN 0 (W), sqrt(2) */
93 1.732050808f
, /* ACN 1 (Y), sqrt(3) */
94 1.732050808f
, /* ACN 2 (Z), sqrt(3) */
95 1.732050808f
, /* ACN 3 (X), sqrt(3) */
96 1.936491673f
, /* ACN 4 (V), sqrt(15)/2 */
97 1.936491673f
, /* ACN 5 (T), sqrt(15)/2 */
98 2.236067978f
, /* ACN 6 (R), sqrt(5) */
99 1.936491673f
, /* ACN 7 (S), sqrt(15)/2 */
100 1.936491673f
, /* ACN 8 (U), sqrt(15)/2 */
101 2.091650066f
, /* ACN 9 (Q), sqrt(35/8) */
102 1.972026594f
, /* ACN 10 (O), sqrt(35)/3 */
103 2.231093404f
, /* ACN 11 (M), sqrt(224/45) */
104 2.645751311f
, /* ACN 12 (K), sqrt(7) */
105 2.231093404f
, /* ACN 13 (L), sqrt(224/45) */
106 1.972026594f
, /* ACN 14 (N), sqrt(35)/3 */
107 2.091650066f
, /* ACN 15 (P), sqrt(35/8) */
111 static const ALfloat SquareMatrixHF
[4][MAX_AMBI_COEFFS
] = {
112 { 0.353553f
, 0.204094f
, 0.0f
, 0.204094f
},
113 { 0.353553f
, -0.204094f
, 0.0f
, 0.204094f
},
114 { 0.353553f
, 0.204094f
, 0.0f
, -0.204094f
},
115 { 0.353553f
, -0.204094f
, 0.0f
, -0.204094f
},
117 static const ALfloat SquareMatrixLF
[4][MAX_AMBI_COEFFS
] = {
118 { 0.25f
, 0.204094f
, 0.0f
, 0.204094f
},
119 { 0.25f
, -0.204094f
, 0.0f
, 0.204094f
},
120 { 0.25f
, 0.204094f
, 0.0f
, -0.204094f
},
121 { 0.25f
, -0.204094f
, 0.0f
, -0.204094f
},
123 static ALfloat SquareEncoder
[4][MAX_AMBI_COEFFS
];
125 static const ALfloat CubeMatrixHF
[8][MAX_AMBI_COEFFS
] = {
126 { 0.25f
, 0.14425f
, 0.14425f
, 0.14425f
},
127 { 0.25f
, -0.14425f
, 0.14425f
, 0.14425f
},
128 { 0.25f
, 0.14425f
, 0.14425f
, -0.14425f
},
129 { 0.25f
, -0.14425f
, 0.14425f
, -0.14425f
},
130 { 0.25f
, 0.14425f
, -0.14425f
, 0.14425f
},
131 { 0.25f
, -0.14425f
, -0.14425f
, 0.14425f
},
132 { 0.25f
, 0.14425f
, -0.14425f
, -0.14425f
},
133 { 0.25f
, -0.14425f
, -0.14425f
, -0.14425f
},
135 static const ALfloat CubeMatrixLF
[8][MAX_AMBI_COEFFS
] = {
136 { 0.125f
, 0.125f
, 0.125f
, 0.125f
},
137 { 0.125f
, -0.125f
, 0.125f
, 0.125f
},
138 { 0.125f
, 0.125f
, 0.125f
, -0.125f
},
139 { 0.125f
, -0.125f
, 0.125f
, -0.125f
},
140 { 0.125f
, 0.125f
, -0.125f
, 0.125f
},
141 { 0.125f
, -0.125f
, -0.125f
, 0.125f
},
142 { 0.125f
, 0.125f
, -0.125f
, -0.125f
},
143 { 0.125f
, -0.125f
, -0.125f
, -0.125f
},
145 static ALfloat CubeEncoder
[8][MAX_AMBI_COEFFS
];
147 static alonce_flag encoder_inited
= AL_ONCE_FLAG_INIT
;
149 static void init_encoder(void)
153 CalcXYZCoeffs(-0.577350269f
, 0.577350269f
, -0.577350269f
, 0.0f
, CubeEncoder
[0]);
154 CalcXYZCoeffs( 0.577350269f
, 0.577350269f
, -0.577350269f
, 0.0f
, CubeEncoder
[1]);
155 CalcXYZCoeffs(-0.577350269f
, 0.577350269f
, 0.577350269f
, 0.0f
, CubeEncoder
[2]);
156 CalcXYZCoeffs( 0.577350269f
, 0.577350269f
, 0.577350269f
, 0.0f
, CubeEncoder
[3]);
157 CalcXYZCoeffs(-0.577350269f
, -0.577350269f
, -0.577350269f
, 0.0f
, CubeEncoder
[4]);
158 CalcXYZCoeffs( 0.577350269f
, -0.577350269f
, -0.577350269f
, 0.0f
, CubeEncoder
[5]);
159 CalcXYZCoeffs(-0.577350269f
, -0.577350269f
, 0.577350269f
, 0.0f
, CubeEncoder
[6]);
160 CalcXYZCoeffs( 0.577350269f
, -0.577350269f
, 0.577350269f
, 0.0f
, CubeEncoder
[7]);
162 CalcXYZCoeffs(-0.707106781f
, 0.0f
, -0.707106781f
, 0.0f
, SquareEncoder
[0]);
163 CalcXYZCoeffs( 0.707106781f
, 0.0f
, -0.707106781f
, 0.0f
, SquareEncoder
[1]);
164 CalcXYZCoeffs(-0.707106781f
, 0.0f
, 0.707106781f
, 0.0f
, SquareEncoder
[2]);
165 CalcXYZCoeffs( 0.707106781f
, 0.0f
, 0.707106781f
, 0.0f
, SquareEncoder
[3]);
169 /* Remove the skipped height-related coefficients for 2D rendering. */
170 SquareEncoder
[i
][2] = SquareEncoder
[i
][3];
171 SquareEncoder
[i
][3] = SquareEncoder
[i
][4];
172 SquareEncoder
[i
][4] = SquareEncoder
[i
][8];
173 SquareEncoder
[i
][5] = SquareEncoder
[i
][9];
174 SquareEncoder
[i
][6] = SquareEncoder
[i
][15];
175 for(j
= 7;j
< MAX_AMBI_COEFFS
;j
++)
176 SquareEncoder
[i
][j
] = 0.0f
;
181 #define MAX_DELAY_LENGTH 128
183 /* NOTE: Low-frequency (LF) fields and BandSplitter filters are unused with
184 * single-band decoding
186 typedef struct BFormatDec
{
187 ALboolean Enabled
[MAX_OUTPUT_CHANNELS
];
189 alignas(16) ALfloat MatrixHF
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
190 alignas(16) ALfloat MatrixLF
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
192 BandSplitter XOver
[MAX_AMBI_COEFFS
];
194 ALfloat (*Samples
)[BUFFERSIZE
];
195 /* These two alias into Samples */
196 ALfloat (*SamplesHF
)[BUFFERSIZE
];
197 ALfloat (*SamplesLF
)[BUFFERSIZE
];
199 alignas(16) ALfloat ChannelMix
[BUFFERSIZE
];
202 alignas(16) ALfloat Buffer
[MAX_DELAY_LENGTH
];
203 ALuint Length
; /* Valid range is [0...MAX_DELAY_LENGTH). */
204 } Delay
[MAX_OUTPUT_CHANNELS
];
207 BandSplitter XOver
[4];
209 const ALfloat (*restrict MatrixHF
)[MAX_AMBI_COEFFS
];
210 const ALfloat (*restrict MatrixLF
)[MAX_AMBI_COEFFS
];
211 const ALfloat (*restrict Encoder
)[MAX_AMBI_COEFFS
];
217 ALboolean Periphonic
;
220 BFormatDec
*bformatdec_alloc()
222 alcall_once(&encoder_inited
, init_encoder
);
223 return al_calloc(16, sizeof(BFormatDec
));
226 void bformatdec_free(BFormatDec
*dec
)
230 al_free(dec
->Samples
);
232 dec
->SamplesHF
= NULL
;
233 dec
->SamplesLF
= NULL
;
235 memset(dec
, 0, sizeof(*dec
));
240 int bformatdec_getOrder(const struct BFormatDec
*dec
)
244 if(dec
->NumChannels
> 9) return 3;
245 if(dec
->NumChannels
> 4) return 2;
246 if(dec
->NumChannels
> 1) return 1;
250 if(dec
->NumChannels
> 5) return 3;
251 if(dec
->NumChannels
> 3) return 2;
252 if(dec
->NumChannels
> 1) return 1;
257 void bformatdec_reset(BFormatDec
*dec
, const AmbDecConf
*conf
, ALuint chancount
, ALuint srate
, const ALuint chanmap
[MAX_OUTPUT_CHANNELS
], int flags
)
259 static const ALuint map2DTo3D
[7] = {
262 const ALfloat
*coeff_scale
= UnitScale
;
263 ALfloat distgain
[MAX_OUTPUT_CHANNELS
];
264 ALfloat maxdist
, ratio
;
267 al_free(dec
->Samples
);
269 dec
->SamplesHF
= NULL
;
270 dec
->SamplesLF
= NULL
;
272 dec
->NumChannels
= chancount
;
273 dec
->Samples
= al_calloc(16, dec
->NumChannels
*2 * sizeof(dec
->Samples
[0]));
274 dec
->SamplesHF
= dec
->Samples
;
275 dec
->SamplesLF
= dec
->SamplesHF
+ dec
->NumChannels
;
277 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
278 dec
->Enabled
[i
] = AL_FALSE
;
279 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
280 dec
->Enabled
[chanmap
[i
]] = AL_TRUE
;
282 if(conf
->CoeffScale
== ADS_SN3D
)
283 coeff_scale
= SN3D2N3DScale
;
284 else if(conf
->CoeffScale
== ADS_FuMa
)
285 coeff_scale
= FuMa2N3DScale
;
287 ratio
= 400.0f
/ (ALfloat
)srate
;
289 bandsplit_init(&dec
->UpSampler
.XOver
[i
], ratio
);
290 if((conf
->ChanMask
& ~0x831b))
292 dec
->UpSampler
.MatrixHF
= CubeMatrixHF
;
293 dec
->UpSampler
.MatrixLF
= CubeMatrixLF
;
294 dec
->UpSampler
.Encoder
= (const ALfloat(*)[MAX_AMBI_COEFFS
])CubeEncoder
;
295 dec
->UpSampler
.NumChannels
= 8;
296 dec
->Periphonic
= AL_TRUE
;
300 dec
->UpSampler
.MatrixHF
= SquareMatrixHF
;
301 dec
->UpSampler
.MatrixLF
= SquareMatrixLF
;
302 dec
->UpSampler
.Encoder
= (const ALfloat(*)[MAX_AMBI_COEFFS
])SquareEncoder
;
303 dec
->UpSampler
.NumChannels
= 4;
304 dec
->Periphonic
= AL_FALSE
;
308 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
310 maxdist
= maxf(maxdist
, conf
->Speakers
[i
].Distance
);
314 memset(dec
->Delay
, 0, sizeof(dec
->Delay
));
315 if((flags
&BFDF_DistanceComp
) && maxdist
> 0.0f
)
317 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
319 ALuint chan
= chanmap
[i
];
322 /* Distance compensation only delays in steps of the sample rate.
323 * This is a bit less accurate since the delay time falls to the
324 * nearest sample time, but it's far simpler as it doesn't have to
325 * deal with phase offsets. This means at 48khz, for instance, the
326 * distance delay will be in steps of about 7 millimeters.
328 delay
= floorf((maxdist
-conf
->Speakers
[i
].Distance
) / SPEEDOFSOUNDMETRESPERSEC
*
329 (ALfloat
)srate
+ 0.5f
);
330 if(delay
>= (ALfloat
)MAX_DELAY_LENGTH
)
331 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
332 al_string_get_cstr(conf
->Speakers
[i
].Name
), delay
, MAX_DELAY_LENGTH
);
334 dec
->Delay
[chan
].Length
= (ALuint
)clampf(delay
, 0.0f
, (ALfloat
)(MAX_DELAY_LENGTH
-1));
335 distgain
[i
] = conf
->Speakers
[i
].Distance
/ maxdist
;
336 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan
,
337 al_string_get_cstr(conf
->Speakers
[i
].Name
), dec
->Delay
[chan
].Length
, distgain
[i
]
342 if(conf
->FreqBands
== 1)
344 dec
->DualBand
= AL_FALSE
;
349 dec
->DualBand
= AL_TRUE
;
351 ratio
= conf
->XOverFreq
/ (ALfloat
)srate
;
352 for(i
= 0;i
< MAX_AMBI_COEFFS
;i
++)
353 bandsplit_init(&dec
->XOver
[i
], ratio
);
355 ratio
= powf(10.0f
, conf
->XOverRatio
/ 40.0f
);
356 memset(dec
->MatrixLF
, 0, sizeof(dec
->MatrixLF
));
357 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
359 ALuint chan
= chanmap
[i
];
367 ALuint l
= map2DTo3D
[j
];
368 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
369 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
370 else if(j
== 3) gain
= conf
->LFOrderGain
[2] / ratio
;
371 else if(j
== 5) gain
= conf
->LFOrderGain
[3] / ratio
;
372 if((conf
->ChanMask
&(1<<l
)))
373 dec
->MatrixLF
[chan
][j
] = conf
->LFMatrix
[i
][k
++] / coeff_scale
[l
] *
379 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
381 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
382 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
383 else if(j
== 4) gain
= conf
->LFOrderGain
[2] / ratio
;
384 else if(j
== 9) gain
= conf
->LFOrderGain
[3] / ratio
;
385 if((conf
->ChanMask
&(1<<j
)))
386 dec
->MatrixLF
[chan
][j
] = conf
->LFMatrix
[i
][k
++] / coeff_scale
[j
] *
393 memset(dec
->MatrixHF
, 0, sizeof(dec
->MatrixHF
));
394 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
396 ALuint chan
= chanmap
[i
];
404 ALuint l
= map2DTo3D
[j
];
405 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
406 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
407 else if(j
== 3) gain
= conf
->HFOrderGain
[2] * ratio
;
408 else if(j
== 5) gain
= conf
->HFOrderGain
[3] * ratio
;
409 if((conf
->ChanMask
&(1<<l
)))
410 dec
->MatrixHF
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[l
] *
416 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
418 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
419 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
420 else if(j
== 4) gain
= conf
->HFOrderGain
[2] * ratio
;
421 else if(j
== 9) gain
= conf
->HFOrderGain
[3] * ratio
;
422 if((conf
->ChanMask
&(1<<j
)))
423 dec
->MatrixHF
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[j
] *
431 static void apply_row(ALfloat
*out
, const ALfloat
*mtx
, ALfloat (*restrict in
)[BUFFERSIZE
], ALuint inchans
, ALuint todo
)
435 for(c
= 0;c
< inchans
;c
++)
437 ALfloat gain
= mtx
[c
];
438 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
440 for(i
= 0;i
< todo
;i
++)
441 out
[i
] += in
[c
][i
] * gain
;
445 void bformatdec_process(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
451 for(i
= 0;i
< dec
->NumChannels
;i
++)
452 bandsplit_process(&dec
->XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
453 InSamples
[i
], SamplesToDo
);
455 for(chan
= 0;chan
< OutChannels
;chan
++)
457 if(!dec
->Enabled
[chan
])
460 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
461 apply_row(dec
->ChannelMix
, dec
->MatrixHF
[chan
], dec
->SamplesHF
,
462 dec
->NumChannels
, SamplesToDo
);
463 apply_row(dec
->ChannelMix
, dec
->MatrixLF
[chan
], dec
->SamplesLF
,
464 dec
->NumChannels
, SamplesToDo
);
466 if(dec
->Delay
[chan
].Length
> 0)
468 const ALuint base
= dec
->Delay
[chan
].Length
;
469 if(SamplesToDo
>= base
)
471 for(i
= 0;i
< base
;i
++)
472 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
473 for(;i
< SamplesToDo
;i
++)
474 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
475 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
476 base
*sizeof(ALfloat
));
480 for(i
= 0;i
< SamplesToDo
;i
++)
481 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
482 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
484 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
485 SamplesToDo
*sizeof(ALfloat
));
488 else for(i
= 0;i
< SamplesToDo
;i
++)
489 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
494 for(chan
= 0;chan
< OutChannels
;chan
++)
496 if(!dec
->Enabled
[chan
])
499 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
500 apply_row(dec
->ChannelMix
, dec
->MatrixHF
[chan
], InSamples
,
501 dec
->NumChannels
, SamplesToDo
);
503 if(dec
->Delay
[chan
].Length
> 0)
505 const ALuint base
= dec
->Delay
[chan
].Length
;
506 if(SamplesToDo
>= base
)
508 for(i
= 0;i
< base
;i
++)
509 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
510 for(;i
< SamplesToDo
;i
++)
511 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
512 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
513 base
*sizeof(ALfloat
));
517 for(i
= 0;i
< SamplesToDo
;i
++)
518 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
519 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
521 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
522 SamplesToDo
*sizeof(ALfloat
));
525 else for(i
= 0;i
< SamplesToDo
;i
++)
526 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
532 void bformatdec_upSample(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint InChannels
, ALuint SamplesToDo
)
536 /* First, split the first-order components into low and high frequency
537 * bands. This assumes SamplesHF and SamplesLF have enough space for first-
538 * order content (to which, this up-sampler is only used with second-order
539 * or higher decoding, so it will).
541 for(i
= 0;i
< InChannels
;i
++)
542 bandsplit_process(&dec
->UpSampler
.XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
543 InSamples
[i
], SamplesToDo
);
545 /* This up-sampler is very simplistic. It essentially decodes the first-
546 * order content to a square channel array (or cube if height is desired),
547 * then encodes those points onto the higher order soundfield.
549 for(k
= 0;k
< dec
->UpSampler
.NumChannels
;k
++)
551 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
552 apply_row(dec
->ChannelMix
, dec
->UpSampler
.MatrixHF
[k
], dec
->SamplesHF
,
553 InChannels
, SamplesToDo
);
554 apply_row(dec
->ChannelMix
, dec
->UpSampler
.MatrixLF
[k
], dec
->SamplesLF
,
555 InChannels
, SamplesToDo
);
557 for(j
= 0;j
< dec
->NumChannels
;j
++)
559 ALfloat gain
= dec
->UpSampler
.Encoder
[k
][j
];
560 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
562 for(i
= 0;i
< SamplesToDo
;i
++)
563 OutBuffer
[j
][i
] += dec
->ChannelMix
[i
] * gain
;