4 #include "bformatdec.h"
6 #include "mixer_defs.h"
13 void bandsplit_init(BandSplitter
*splitter
, ALfloat freq_mult
)
15 ALfloat w
= freq_mult
* F_TAU
;
18 splitter
->coeff
= (sinf(w
) - 1.0f
) / cw
;
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
)
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 /* 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 RowMixerFunc MixMatrixRow
= MixRow_C
;
167 static alonce_flag bformatdec_inited
= AL_ONCE_FLAG_INIT
;
169 static void init_bformatdec(void)
173 MixMatrixRow
= SelectRowMixer();
175 for(i
= 0;i
< COUNTOF(Ambi3DPoints
);i
++)
176 CalcDirectionCoeffs(Ambi3DPoints
[i
], 0.0f
, Ambi3DEncoder
[i
]);
178 for(i
= 0;i
< COUNTOF(Ambi2DPoints
);i
++)
180 CalcDirectionCoeffs(Ambi2DPoints
[i
], 0.0f
, Ambi2DEncoder
[i
]);
182 /* Remove the skipped height-related coefficients for 2D rendering. */
183 Ambi2DEncoder
[i
][2] = Ambi2DEncoder
[i
][3];
184 Ambi2DEncoder
[i
][3] = Ambi2DEncoder
[i
][4];
185 Ambi2DEncoder
[i
][4] = Ambi2DEncoder
[i
][8];
186 Ambi2DEncoder
[i
][5] = Ambi2DEncoder
[i
][9];
187 Ambi2DEncoder
[i
][6] = Ambi2DEncoder
[i
][15];
188 for(j
= 7;j
< MAX_AMBI_COEFFS
;j
++)
189 Ambi2DEncoder
[i
][j
] = 0.0f
;
194 #define MAX_DELAY_LENGTH 128
196 /* NOTE: BandSplitter filters are unused with single-band decoding */
197 typedef struct BFormatDec
{
198 ALboolean Enabled
[MAX_OUTPUT_CHANNELS
];
201 alignas(16) ALfloat Dual
[MAX_OUTPUT_CHANNELS
][FB_Max
][MAX_AMBI_COEFFS
];
202 alignas(16) ALfloat Single
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
205 BandSplitter XOver
[MAX_AMBI_COEFFS
];
207 ALfloat (*Samples
)[BUFFERSIZE
];
208 /* These two alias into Samples */
209 ALfloat (*SamplesHF
)[BUFFERSIZE
];
210 ALfloat (*SamplesLF
)[BUFFERSIZE
];
212 alignas(16) ALfloat ChannelMix
[BUFFERSIZE
];
215 alignas(16) ALfloat Buffer
[MAX_DELAY_LENGTH
];
216 ALuint Length
; /* Valid range is [0...MAX_DELAY_LENGTH). */
217 } Delay
[MAX_OUTPUT_CHANNELS
];
220 BandSplitter XOver
[4];
222 ALfloat Gains
[4][MAX_OUTPUT_CHANNELS
][FB_Max
];
227 ALboolean Periphonic
;
230 BFormatDec
*bformatdec_alloc()
232 alcall_once(&bformatdec_inited
, init_bformatdec
);
233 return al_calloc(16, sizeof(BFormatDec
));
236 void bformatdec_free(BFormatDec
*dec
)
240 al_free(dec
->Samples
);
242 dec
->SamplesHF
= NULL
;
243 dec
->SamplesLF
= NULL
;
245 memset(dec
, 0, sizeof(*dec
));
250 int bformatdec_getOrder(const struct BFormatDec
*dec
)
254 if(dec
->NumChannels
> 9) return 3;
255 if(dec
->NumChannels
> 4) return 2;
256 if(dec
->NumChannels
> 1) return 1;
260 if(dec
->NumChannels
> 5) return 3;
261 if(dec
->NumChannels
> 3) return 2;
262 if(dec
->NumChannels
> 1) return 1;
267 void bformatdec_reset(BFormatDec
*dec
, const AmbDecConf
*conf
, ALuint chancount
, ALuint srate
, const ALuint chanmap
[MAX_OUTPUT_CHANNELS
], int flags
)
269 static const ALuint map2DTo3D
[MAX_AMBI2D_COEFFS
] = {
272 const ALfloat
*coeff_scale
= UnitScale
;
273 ALfloat distgain
[MAX_OUTPUT_CHANNELS
];
274 ALfloat maxdist
, ratio
;
277 al_free(dec
->Samples
);
279 dec
->SamplesHF
= NULL
;
280 dec
->SamplesLF
= NULL
;
282 dec
->NumChannels
= chancount
;
283 dec
->Samples
= al_calloc(16, dec
->NumChannels
*2 * sizeof(dec
->Samples
[0]));
284 dec
->SamplesHF
= dec
->Samples
;
285 dec
->SamplesLF
= dec
->SamplesHF
+ dec
->NumChannels
;
287 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
288 dec
->Enabled
[i
] = AL_FALSE
;
289 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
290 dec
->Enabled
[chanmap
[i
]] = AL_TRUE
;
292 if(conf
->CoeffScale
== ADS_SN3D
)
293 coeff_scale
= SN3D2N3DScale
;
294 else if(conf
->CoeffScale
== ADS_FuMa
)
295 coeff_scale
= FuMa2N3DScale
;
297 ratio
= 400.0f
/ (ALfloat
)srate
;
299 bandsplit_init(&dec
->UpSampler
.XOver
[i
], ratio
);
300 memset(dec
->UpSampler
.Gains
, 0, sizeof(dec
->UpSampler
.Gains
));
301 if((conf
->ChanMask
&AMBI_PERIPHONIC_MASK
))
303 /* Combine the matrices that do the in->virt and virt->out conversions
304 * so we get a single in->out conversion.
308 for(j
= 0;j
< dec
->NumChannels
;j
++)
310 ALfloat
*gains
= dec
->UpSampler
.Gains
[i
][j
];
311 for(k
= 0;k
< COUNTOF(Ambi3DDecoder
);k
++)
313 gains
[FB_HighFreq
] += Ambi3DDecoder
[k
][FB_HighFreq
][i
]*Ambi3DEncoder
[k
][j
];
314 gains
[FB_LowFreq
] += Ambi3DDecoder
[k
][FB_LowFreq
][i
]*Ambi3DEncoder
[k
][j
];
319 dec
->Periphonic
= AL_TRUE
;
325 for(j
= 0;j
< dec
->NumChannels
;j
++)
327 ALfloat
*gains
= dec
->UpSampler
.Gains
[i
][j
];
328 for(k
= 0;k
< COUNTOF(Ambi2DDecoder
);k
++)
330 gains
[FB_HighFreq
] += Ambi2DDecoder
[k
][FB_HighFreq
][i
]*Ambi2DEncoder
[k
][j
];
331 gains
[FB_LowFreq
] += Ambi2DDecoder
[k
][FB_LowFreq
][i
]*Ambi2DEncoder
[k
][j
];
336 dec
->Periphonic
= AL_FALSE
;
340 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
342 maxdist
= maxf(maxdist
, conf
->Speakers
[i
].Distance
);
346 memset(dec
->Delay
, 0, sizeof(dec
->Delay
));
347 if((flags
&BFDF_DistanceComp
) && maxdist
> 0.0f
)
349 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
351 ALuint chan
= chanmap
[i
];
354 /* Distance compensation only delays in steps of the sample rate.
355 * This is a bit less accurate since the delay time falls to the
356 * nearest sample time, but it's far simpler as it doesn't have to
357 * deal with phase offsets. This means at 48khz, for instance, the
358 * distance delay will be in steps of about 7 millimeters.
360 delay
= floorf((maxdist
-conf
->Speakers
[i
].Distance
) / SPEEDOFSOUNDMETRESPERSEC
*
361 (ALfloat
)srate
+ 0.5f
);
362 if(delay
>= (ALfloat
)MAX_DELAY_LENGTH
)
363 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
364 al_string_get_cstr(conf
->Speakers
[i
].Name
), delay
, MAX_DELAY_LENGTH
);
366 dec
->Delay
[chan
].Length
= (ALuint
)clampf(delay
, 0.0f
, (ALfloat
)(MAX_DELAY_LENGTH
-1));
367 distgain
[i
] = conf
->Speakers
[i
].Distance
/ maxdist
;
368 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan
,
369 al_string_get_cstr(conf
->Speakers
[i
].Name
), dec
->Delay
[chan
].Length
, distgain
[i
]
374 memset(&dec
->Matrix
, 0, sizeof(dec
->Matrix
));
375 if(conf
->FreqBands
== 1)
377 dec
->DualBand
= AL_FALSE
;
378 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
380 ALuint chan
= chanmap
[i
];
386 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
388 ALuint l
= map2DTo3D
[j
];
389 if(j
== 0) gain
= conf
->HFOrderGain
[0];
390 else if(j
== 1) gain
= conf
->HFOrderGain
[1];
391 else if(j
== 3) gain
= conf
->HFOrderGain
[2];
392 else if(j
== 5) gain
= conf
->HFOrderGain
[3];
393 if((conf
->ChanMask
&(1<<l
)))
394 dec
->Matrix
.Single
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[l
] *
400 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
402 if(j
== 0) gain
= conf
->HFOrderGain
[0];
403 else if(j
== 1) gain
= conf
->HFOrderGain
[1];
404 else if(j
== 4) gain
= conf
->HFOrderGain
[2];
405 else if(j
== 9) gain
= conf
->HFOrderGain
[3];
406 if((conf
->ChanMask
&(1<<j
)))
407 dec
->Matrix
.Single
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[j
] *
415 dec
->DualBand
= AL_TRUE
;
417 ratio
= conf
->XOverFreq
/ (ALfloat
)srate
;
418 for(i
= 0;i
< MAX_AMBI_COEFFS
;i
++)
419 bandsplit_init(&dec
->XOver
[i
], ratio
);
421 ratio
= powf(10.0f
, conf
->XOverRatio
/ 40.0f
);
422 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
424 ALuint chan
= chanmap
[i
];
430 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
432 ALuint l
= map2DTo3D
[j
];
433 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
434 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
435 else if(j
== 3) gain
= conf
->HFOrderGain
[2] * ratio
;
436 else if(j
== 5) gain
= conf
->HFOrderGain
[3] * ratio
;
437 if((conf
->ChanMask
&(1<<l
)))
438 dec
->Matrix
.Dual
[chan
][FB_HighFreq
][j
] = conf
->HFMatrix
[i
][k
++] /
439 coeff_scale
[l
] * gain
*
442 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
444 ALuint l
= map2DTo3D
[j
];
445 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
446 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
447 else if(j
== 3) gain
= conf
->LFOrderGain
[2] / ratio
;
448 else if(j
== 5) gain
= conf
->LFOrderGain
[3] / ratio
;
449 if((conf
->ChanMask
&(1<<l
)))
450 dec
->Matrix
.Dual
[chan
][FB_LowFreq
][j
] = conf
->LFMatrix
[i
][k
++] /
451 coeff_scale
[l
] * gain
*
457 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
459 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
460 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
461 else if(j
== 4) gain
= conf
->HFOrderGain
[2] * ratio
;
462 else if(j
== 9) gain
= conf
->HFOrderGain
[3] * ratio
;
463 if((conf
->ChanMask
&(1<<j
)))
464 dec
->Matrix
.Dual
[chan
][FB_HighFreq
][j
] = conf
->HFMatrix
[i
][k
++] /
465 coeff_scale
[j
] * gain
*
468 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
470 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
471 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
472 else if(j
== 4) gain
= conf
->LFOrderGain
[2] / ratio
;
473 else if(j
== 9) gain
= conf
->LFOrderGain
[3] / ratio
;
474 if((conf
->ChanMask
&(1<<j
)))
475 dec
->Matrix
.Dual
[chan
][FB_LowFreq
][j
] = conf
->LFMatrix
[i
][k
++] /
476 coeff_scale
[j
] * gain
*
485 void bformatdec_process(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, const ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
491 for(i
= 0;i
< dec
->NumChannels
;i
++)
492 bandsplit_process(&dec
->XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
493 InSamples
[i
], SamplesToDo
);
495 for(chan
= 0;chan
< OutChannels
;chan
++)
497 if(!dec
->Enabled
[chan
])
500 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
501 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Dual
[chan
][FB_HighFreq
],
502 SAFE_CONST(ALfloatBUFFERSIZE
*,dec
->SamplesHF
), dec
->NumChannels
, 0,
505 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Dual
[chan
][FB_LowFreq
],
506 SAFE_CONST(ALfloatBUFFERSIZE
*,dec
->SamplesLF
), dec
->NumChannels
, 0,
510 if(dec
->Delay
[chan
].Length
> 0)
512 const ALuint base
= dec
->Delay
[chan
].Length
;
513 if(SamplesToDo
>= base
)
515 for(i
= 0;i
< base
;i
++)
516 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
517 for(;i
< SamplesToDo
;i
++)
518 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
519 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
520 base
*sizeof(ALfloat
));
524 for(i
= 0;i
< SamplesToDo
;i
++)
525 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
526 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
528 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
529 SamplesToDo
*sizeof(ALfloat
));
532 else for(i
= 0;i
< SamplesToDo
;i
++)
533 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
538 for(chan
= 0;chan
< OutChannels
;chan
++)
540 if(!dec
->Enabled
[chan
])
543 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
544 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Single
[chan
], InSamples
,
545 dec
->NumChannels
, 0, SamplesToDo
);
547 if(dec
->Delay
[chan
].Length
> 0)
549 const ALuint base
= dec
->Delay
[chan
].Length
;
550 if(SamplesToDo
>= base
)
552 for(i
= 0;i
< base
;i
++)
553 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
554 for(;i
< SamplesToDo
;i
++)
555 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
556 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
557 base
*sizeof(ALfloat
));
561 for(i
= 0;i
< SamplesToDo
;i
++)
562 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
563 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
565 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
566 SamplesToDo
*sizeof(ALfloat
));
569 else for(i
= 0;i
< SamplesToDo
;i
++)
570 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
576 void bformatdec_upSample(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], const ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint InChannels
, ALuint SamplesToDo
)
580 /* This up-sampler is very simplistic. It essentially decodes the first-
581 * order content to a square channel array (or cube if height is desired),
582 * then encodes those points onto the higher order soundfield. The decoder
583 * and encoder matrices have been combined to directly convert each input
584 * channel to the output, without the need for storing the virtual channel
587 for(i
= 0;i
< InChannels
;i
++)
589 /* First, split the first-order components into low and high frequency
592 bandsplit_process(&dec
->UpSampler
.XOver
[i
],
593 dec
->Samples
[FB_HighFreq
], dec
->Samples
[FB_LowFreq
],
594 InSamples
[i
], SamplesToDo
597 /* Now write each band to the output. */
598 for(j
= 0;j
< dec
->NumChannels
;j
++)
599 MixMatrixRow(OutBuffer
[j
], dec
->UpSampler
.Gains
[i
][j
],
600 SAFE_CONST(ALfloatBUFFERSIZE
*,dec
->Samples
), FB_Max
, 0,
607 typedef struct AmbiUpsampler
{
608 alignas(16) ALfloat Samples
[FB_Max
][BUFFERSIZE
];
610 BandSplitter XOver
[4];
612 ALfloat Gains
[4][MAX_OUTPUT_CHANNELS
][FB_Max
];
615 AmbiUpsampler
*ambiup_alloc()
617 alcall_once(&bformatdec_inited
, init_bformatdec
);
618 return al_calloc(16, sizeof(AmbiUpsampler
));
621 void ambiup_free(struct AmbiUpsampler
*ambiup
)
626 void ambiup_reset(struct AmbiUpsampler
*ambiup
, const ALCdevice
*device
)
628 ALfloat gains
[8][MAX_OUTPUT_CHANNELS
];
632 ratio
= 400.0f
/ (ALfloat
)device
->Frequency
;
634 bandsplit_init(&ambiup
->XOver
[i
], ratio
);
636 for(i
= 0;i
< COUNTOF(Ambi3DEncoder
);i
++)
637 ComputePanningGains(device
->Dry
, Ambi3DEncoder
[i
], 1.0f
, gains
[i
]);
639 memset(ambiup
->Gains
, 0, sizeof(ambiup
->Gains
));
642 for(j
= 0;j
< device
->Dry
.NumChannels
;j
++)
644 for(k
= 0;k
< COUNTOF(Ambi3DDecoder
);k
++)
646 ambiup
->Gains
[i
][j
][FB_HighFreq
] += Ambi3DDecoder
[k
][FB_HighFreq
][i
]*gains
[k
][j
];
647 ambiup
->Gains
[i
][j
][FB_LowFreq
] += Ambi3DDecoder
[k
][FB_LowFreq
][i
]*gains
[k
][j
];
653 void ambiup_process(struct AmbiUpsampler
*ambiup
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, const ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
659 bandsplit_process(&ambiup
->XOver
[i
],
660 ambiup
->Samples
[FB_HighFreq
], ambiup
->Samples
[FB_LowFreq
],
661 InSamples
[i
], SamplesToDo
664 for(j
= 0;j
< OutChannels
;j
++)
665 MixMatrixRow(OutBuffer
[j
], ambiup
->Gains
[i
][j
],
666 SAFE_CONST(ALfloatBUFFERSIZE
*,ambiup
->Samples
), FB_Max
, 0,