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 Ambi2DEncoderT
[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 Ambi3DEncoderT
[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
, Ambi3DEncoderT
[i
]);
178 for(i
= 0;i
< COUNTOF(Ambi2DPoints
);i
++)
180 CalcDirectionCoeffs(Ambi2DPoints
[i
], 0.0f
, Ambi2DEncoderT
[i
]);
182 /* Remove the skipped height-related coefficients for 2D rendering. */
183 Ambi2DEncoderT
[i
][2] = Ambi2DEncoderT
[i
][3];
184 Ambi2DEncoderT
[i
][3] = Ambi2DEncoderT
[i
][4];
185 Ambi2DEncoderT
[i
][4] = Ambi2DEncoderT
[i
][8];
186 Ambi2DEncoderT
[i
][5] = Ambi2DEncoderT
[i
][9];
187 Ambi2DEncoderT
[i
][6] = Ambi2DEncoderT
[i
][15];
188 for(j
= 7;j
< MAX_AMBI_COEFFS
;j
++)
189 Ambi2DEncoderT
[i
][j
] = 0.0f
;
194 /* This typedef is needed for SAFE_CONST to work. */
195 typedef ALfloat ALfloatMAX_AMBI_COEFFS
[MAX_AMBI_COEFFS
];
197 static void GenUpsamplerGains(const ALfloat (*restrict EncoderT
)[MAX_AMBI_COEFFS
],
198 const ALfloat (*restrict Decoder
)[FB_Max
][MAX_AMBI_COEFFS
],
200 ALfloat (*restrict OutGains
)[MAX_OUTPUT_CHANNELS
][FB_Max
],
205 /* Combine the matrices that do the in->virt and virt->out conversions so
206 * we get a single in->out conversion. NOTE: the Encoder matrix and output
207 * are transposed, so the input channels line up with the rows and the
208 * output channels line up with the columns.
212 for(j
= 0;j
< OutChannels
;j
++)
214 ALfloat hfgain
=0.0f
, lfgain
=0.0f
;
215 for(k
= 0;k
< InChannels
;k
++)
217 hfgain
+= Decoder
[k
][FB_HighFreq
][i
]*EncoderT
[k
][j
];
218 lfgain
+= Decoder
[k
][FB_LowFreq
][i
]*EncoderT
[k
][j
];
220 OutGains
[i
][j
][FB_HighFreq
] = hfgain
;
221 OutGains
[i
][j
][FB_LowFreq
] = lfgain
;
227 #define MAX_DELAY_LENGTH 128
229 /* NOTE: BandSplitter filters are unused with single-band decoding */
230 typedef struct BFormatDec
{
231 ALboolean Enabled
[MAX_OUTPUT_CHANNELS
];
234 alignas(16) ALfloat Dual
[MAX_OUTPUT_CHANNELS
][FB_Max
][MAX_AMBI_COEFFS
];
235 alignas(16) ALfloat Single
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
238 BandSplitter XOver
[MAX_AMBI_COEFFS
];
240 ALfloat (*Samples
)[BUFFERSIZE
];
241 /* These two alias into Samples */
242 ALfloat (*SamplesHF
)[BUFFERSIZE
];
243 ALfloat (*SamplesLF
)[BUFFERSIZE
];
245 alignas(16) ALfloat ChannelMix
[BUFFERSIZE
];
248 alignas(16) ALfloat Buffer
[MAX_DELAY_LENGTH
];
249 ALuint Length
; /* Valid range is [0...MAX_DELAY_LENGTH). */
250 } Delay
[MAX_OUTPUT_CHANNELS
];
253 BandSplitter XOver
[4];
255 ALfloat Gains
[4][MAX_OUTPUT_CHANNELS
][FB_Max
];
260 ALboolean Periphonic
;
263 BFormatDec
*bformatdec_alloc()
265 alcall_once(&bformatdec_inited
, init_bformatdec
);
266 return al_calloc(16, sizeof(BFormatDec
));
269 void bformatdec_free(BFormatDec
*dec
)
273 al_free(dec
->Samples
);
275 dec
->SamplesHF
= NULL
;
276 dec
->SamplesLF
= NULL
;
278 memset(dec
, 0, sizeof(*dec
));
283 int bformatdec_getOrder(const struct BFormatDec
*dec
)
287 if(dec
->NumChannels
> 9) return 3;
288 if(dec
->NumChannels
> 4) return 2;
289 if(dec
->NumChannels
> 1) return 1;
293 if(dec
->NumChannels
> 5) return 3;
294 if(dec
->NumChannels
> 3) return 2;
295 if(dec
->NumChannels
> 1) return 1;
300 void bformatdec_reset(BFormatDec
*dec
, const AmbDecConf
*conf
, ALuint chancount
, ALuint srate
, const ALuint chanmap
[MAX_OUTPUT_CHANNELS
], int flags
)
302 static const ALuint map2DTo3D
[MAX_AMBI2D_COEFFS
] = {
305 const ALfloat
*coeff_scale
= UnitScale
;
306 ALfloat distgain
[MAX_OUTPUT_CHANNELS
];
307 ALfloat maxdist
, ratio
;
310 al_free(dec
->Samples
);
312 dec
->SamplesHF
= NULL
;
313 dec
->SamplesLF
= NULL
;
315 dec
->NumChannels
= chancount
;
316 dec
->Samples
= al_calloc(16, dec
->NumChannels
*2 * sizeof(dec
->Samples
[0]));
317 dec
->SamplesHF
= dec
->Samples
;
318 dec
->SamplesLF
= dec
->SamplesHF
+ dec
->NumChannels
;
320 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
321 dec
->Enabled
[i
] = AL_FALSE
;
322 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
323 dec
->Enabled
[chanmap
[i
]] = AL_TRUE
;
325 if(conf
->CoeffScale
== ADS_SN3D
)
326 coeff_scale
= SN3D2N3DScale
;
327 else if(conf
->CoeffScale
== ADS_FuMa
)
328 coeff_scale
= FuMa2N3DScale
;
330 ratio
= 400.0f
/ (ALfloat
)srate
;
332 bandsplit_init(&dec
->UpSampler
.XOver
[i
], ratio
);
333 memset(dec
->UpSampler
.Gains
, 0, sizeof(dec
->UpSampler
.Gains
));
334 if((conf
->ChanMask
&AMBI_PERIPHONIC_MASK
))
336 GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS
*,Ambi3DEncoderT
),
337 Ambi3DDecoder
, COUNTOF(Ambi3DDecoder
),
338 dec
->UpSampler
.Gains
, dec
->NumChannels
);
339 dec
->Periphonic
= AL_TRUE
;
343 GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS
*,Ambi2DEncoderT
),
344 Ambi2DDecoder
, COUNTOF(Ambi2DDecoder
),
345 dec
->UpSampler
.Gains
, dec
->NumChannels
);
346 dec
->Periphonic
= AL_FALSE
;
350 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
352 maxdist
= maxf(maxdist
, conf
->Speakers
[i
].Distance
);
356 memset(dec
->Delay
, 0, sizeof(dec
->Delay
));
357 if((flags
&BFDF_DistanceComp
) && maxdist
> 0.0f
)
359 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
361 ALuint chan
= chanmap
[i
];
364 /* Distance compensation only delays in steps of the sample rate.
365 * This is a bit less accurate since the delay time falls to the
366 * nearest sample time, but it's far simpler as it doesn't have to
367 * deal with phase offsets. This means at 48khz, for instance, the
368 * distance delay will be in steps of about 7 millimeters.
370 delay
= floorf((maxdist
-conf
->Speakers
[i
].Distance
) / SPEEDOFSOUNDMETRESPERSEC
*
371 (ALfloat
)srate
+ 0.5f
);
372 if(delay
>= (ALfloat
)MAX_DELAY_LENGTH
)
373 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
374 al_string_get_cstr(conf
->Speakers
[i
].Name
), delay
, MAX_DELAY_LENGTH
);
376 dec
->Delay
[chan
].Length
= (ALuint
)clampf(delay
, 0.0f
, (ALfloat
)(MAX_DELAY_LENGTH
-1));
377 distgain
[i
] = conf
->Speakers
[i
].Distance
/ maxdist
;
378 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan
,
379 al_string_get_cstr(conf
->Speakers
[i
].Name
), dec
->Delay
[chan
].Length
, distgain
[i
]
384 memset(&dec
->Matrix
, 0, sizeof(dec
->Matrix
));
385 if(conf
->FreqBands
== 1)
387 dec
->DualBand
= AL_FALSE
;
388 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
390 ALuint chan
= chanmap
[i
];
396 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
398 ALuint l
= map2DTo3D
[j
];
399 if(j
== 0) gain
= conf
->HFOrderGain
[0];
400 else if(j
== 1) gain
= conf
->HFOrderGain
[1];
401 else if(j
== 3) gain
= conf
->HFOrderGain
[2];
402 else if(j
== 5) gain
= conf
->HFOrderGain
[3];
403 if((conf
->ChanMask
&(1<<l
)))
404 dec
->Matrix
.Single
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[l
] *
410 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
412 if(j
== 0) gain
= conf
->HFOrderGain
[0];
413 else if(j
== 1) gain
= conf
->HFOrderGain
[1];
414 else if(j
== 4) gain
= conf
->HFOrderGain
[2];
415 else if(j
== 9) gain
= conf
->HFOrderGain
[3];
416 if((conf
->ChanMask
&(1<<j
)))
417 dec
->Matrix
.Single
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[j
] *
425 dec
->DualBand
= AL_TRUE
;
427 ratio
= conf
->XOverFreq
/ (ALfloat
)srate
;
428 for(i
= 0;i
< MAX_AMBI_COEFFS
;i
++)
429 bandsplit_init(&dec
->XOver
[i
], ratio
);
431 ratio
= powf(10.0f
, conf
->XOverRatio
/ 40.0f
);
432 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
434 ALuint chan
= chanmap
[i
];
440 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
442 ALuint l
= map2DTo3D
[j
];
443 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
444 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
445 else if(j
== 3) gain
= conf
->HFOrderGain
[2] * ratio
;
446 else if(j
== 5) gain
= conf
->HFOrderGain
[3] * ratio
;
447 if((conf
->ChanMask
&(1<<l
)))
448 dec
->Matrix
.Dual
[chan
][FB_HighFreq
][j
] = conf
->HFMatrix
[i
][k
++] /
449 coeff_scale
[l
] * gain
*
452 for(j
= 0,k
= 0;j
< MAX_AMBI2D_COEFFS
;j
++)
454 ALuint l
= map2DTo3D
[j
];
455 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
456 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
457 else if(j
== 3) gain
= conf
->LFOrderGain
[2] / ratio
;
458 else if(j
== 5) gain
= conf
->LFOrderGain
[3] / ratio
;
459 if((conf
->ChanMask
&(1<<l
)))
460 dec
->Matrix
.Dual
[chan
][FB_LowFreq
][j
] = conf
->LFMatrix
[i
][k
++] /
461 coeff_scale
[l
] * gain
*
467 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
469 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
470 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
471 else if(j
== 4) gain
= conf
->HFOrderGain
[2] * ratio
;
472 else if(j
== 9) gain
= conf
->HFOrderGain
[3] * ratio
;
473 if((conf
->ChanMask
&(1<<j
)))
474 dec
->Matrix
.Dual
[chan
][FB_HighFreq
][j
] = conf
->HFMatrix
[i
][k
++] /
475 coeff_scale
[j
] * gain
*
478 for(j
= 0,k
= 0;j
< MAX_AMBI_COEFFS
;j
++)
480 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
481 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
482 else if(j
== 4) gain
= conf
->LFOrderGain
[2] / ratio
;
483 else if(j
== 9) gain
= conf
->LFOrderGain
[3] / ratio
;
484 if((conf
->ChanMask
&(1<<j
)))
485 dec
->Matrix
.Dual
[chan
][FB_LowFreq
][j
] = conf
->LFMatrix
[i
][k
++] /
486 coeff_scale
[j
] * gain
*
495 void bformatdec_process(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, const ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
501 for(i
= 0;i
< dec
->NumChannels
;i
++)
502 bandsplit_process(&dec
->XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
503 InSamples
[i
], SamplesToDo
);
505 for(chan
= 0;chan
< OutChannels
;chan
++)
507 if(!dec
->Enabled
[chan
])
510 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
511 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Dual
[chan
][FB_HighFreq
],
512 SAFE_CONST(ALfloatBUFFERSIZE
*,dec
->SamplesHF
), dec
->NumChannels
, 0,
515 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Dual
[chan
][FB_LowFreq
],
516 SAFE_CONST(ALfloatBUFFERSIZE
*,dec
->SamplesLF
), dec
->NumChannels
, 0,
520 if(dec
->Delay
[chan
].Length
> 0)
522 const ALuint base
= dec
->Delay
[chan
].Length
;
523 if(SamplesToDo
>= base
)
525 for(i
= 0;i
< base
;i
++)
526 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
527 for(;i
< SamplesToDo
;i
++)
528 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
529 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
530 base
*sizeof(ALfloat
));
534 for(i
= 0;i
< SamplesToDo
;i
++)
535 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
536 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
538 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
539 SamplesToDo
*sizeof(ALfloat
));
542 else for(i
= 0;i
< SamplesToDo
;i
++)
543 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
548 for(chan
= 0;chan
< OutChannels
;chan
++)
550 if(!dec
->Enabled
[chan
])
553 memset(dec
->ChannelMix
, 0, SamplesToDo
*sizeof(ALfloat
));
554 MixMatrixRow(dec
->ChannelMix
, dec
->Matrix
.Single
[chan
], InSamples
,
555 dec
->NumChannels
, 0, SamplesToDo
);
557 if(dec
->Delay
[chan
].Length
> 0)
559 const ALuint base
= dec
->Delay
[chan
].Length
;
560 if(SamplesToDo
>= base
)
562 for(i
= 0;i
< base
;i
++)
563 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
564 for(;i
< SamplesToDo
;i
++)
565 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
-base
];
566 memcpy(dec
->Delay
[chan
].Buffer
, &dec
->ChannelMix
[SamplesToDo
-base
],
567 base
*sizeof(ALfloat
));
571 for(i
= 0;i
< SamplesToDo
;i
++)
572 OutBuffer
[chan
][i
] += dec
->Delay
[chan
].Buffer
[i
];
573 memmove(dec
->Delay
[chan
].Buffer
, dec
->Delay
[chan
].Buffer
+SamplesToDo
,
575 memcpy(dec
->Delay
[chan
].Buffer
+base
-SamplesToDo
, dec
->ChannelMix
,
576 SamplesToDo
*sizeof(ALfloat
));
579 else for(i
= 0;i
< SamplesToDo
;i
++)
580 OutBuffer
[chan
][i
] += dec
->ChannelMix
[i
];
586 void bformatdec_upSample(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], const ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint InChannels
, ALuint SamplesToDo
)
590 /* This up-sampler is very simplistic. It essentially decodes the first-
591 * order content to a square channel array (or cube if height is desired),
592 * then encodes those points onto the higher order soundfield. The decoder
593 * and encoder matrices have been combined to directly convert each input
594 * channel to the output, without the need for storing the virtual channel
597 for(i
= 0;i
< InChannels
;i
++)
599 /* First, split the first-order components into low and high frequency
602 bandsplit_process(&dec
->UpSampler
.XOver
[i
],
603 dec
->Samples
[FB_HighFreq
], dec
->Samples
[FB_LowFreq
],
604 InSamples
[i
], SamplesToDo
607 /* Now write each band to the output. */
608 for(j
= 0;j
< dec
->NumChannels
;j
++)
609 MixMatrixRow(OutBuffer
[j
], dec
->UpSampler
.Gains
[i
][j
],
610 SAFE_CONST(ALfloatBUFFERSIZE
*,dec
->Samples
), FB_Max
, 0,
617 typedef struct AmbiUpsampler
{
618 alignas(16) ALfloat Samples
[FB_Max
][BUFFERSIZE
];
620 BandSplitter XOver
[4];
622 ALfloat Gains
[4][MAX_OUTPUT_CHANNELS
][FB_Max
];
625 AmbiUpsampler
*ambiup_alloc()
627 alcall_once(&bformatdec_inited
, init_bformatdec
);
628 return al_calloc(16, sizeof(AmbiUpsampler
));
631 void ambiup_free(struct AmbiUpsampler
*ambiup
)
636 void ambiup_reset(struct AmbiUpsampler
*ambiup
, const ALCdevice
*device
)
638 ALfloat gains
[8][MAX_OUTPUT_CHANNELS
];
642 ratio
= 400.0f
/ (ALfloat
)device
->Frequency
;
644 bandsplit_init(&ambiup
->XOver
[i
], ratio
);
646 for(i
= 0;i
< COUNTOF(Ambi3DEncoderT
);i
++)
647 ComputePanningGains(device
->Dry
, Ambi3DEncoderT
[i
], 1.0f
, gains
[i
]);
649 memset(ambiup
->Gains
, 0, sizeof(ambiup
->Gains
));
650 GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS
*,gains
),
651 Ambi3DDecoder
, COUNTOF(Ambi3DDecoder
),
652 ambiup
->Gains
, device
->Dry
.NumChannels
);
655 void ambiup_process(struct AmbiUpsampler
*ambiup
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, const ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
661 bandsplit_process(&ambiup
->XOver
[i
],
662 ambiup
->Samples
[FB_HighFreq
], ambiup
->Samples
[FB_LowFreq
],
663 InSamples
[i
], SamplesToDo
666 for(j
= 0;j
< OutChannels
;j
++)
667 MixMatrixRow(OutBuffer
[j
], ambiup
->Gains
[i
][j
],
668 SAFE_CONST(ALfloatBUFFERSIZE
*,ambiup
->Samples
), FB_Max
, 0,