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 inline RowMixerFunc
SelectRowMixer(void)
167 if((CPUCapFlags
&CPU_CAP_SSE
))
171 if((CPUCapFlags
&CPU_CAP_NEON
))
177 static RowMixerFunc MixMatrixRow
= MixRow_C
;
180 static alonce_flag bformatdec_inited
= AL_ONCE_FLAG_INIT
;
182 static void init_bformatdec(void)
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
];
214 alignas(16) ALfloat Dual
[MAX_OUTPUT_CHANNELS
][FB_Max
][MAX_AMBI_COEFFS
];
215 alignas(16) ALfloat Single
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
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
];
228 alignas(16) ALfloat Buffer
[MAX_DELAY_LENGTH
];
229 ALuint Length
; /* Valid range is [0...MAX_DELAY_LENGTH). */
230 } Delay
[MAX_OUTPUT_CHANNELS
];
233 BandSplitter XOver
[4];
235 ALfloat Gains
[4][MAX_OUTPUT_CHANNELS
][FB_Max
];
240 ALboolean Periphonic
;
243 BFormatDec
*bformatdec_alloc()
245 alcall_once(&bformatdec_inited
, init_bformatdec
);
246 return al_calloc(16, sizeof(BFormatDec
));
249 void bformatdec_free(BFormatDec
*dec
)
253 al_free(dec
->Samples
);
255 dec
->SamplesHF
= NULL
;
256 dec
->SamplesLF
= NULL
;
258 memset(dec
, 0, sizeof(*dec
));
263 int bformatdec_getOrder(const struct BFormatDec
*dec
)
267 if(dec
->NumChannels
> 9) return 3;
268 if(dec
->NumChannels
> 4) return 2;
269 if(dec
->NumChannels
> 1) return 1;
273 if(dec
->NumChannels
> 5) return 3;
274 if(dec
->NumChannels
> 3) return 2;
275 if(dec
->NumChannels
> 1) return 1;
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
] = {
285 const ALfloat
*coeff_scale
= UnitScale
;
286 ALfloat distgain
[MAX_OUTPUT_CHANNELS
];
287 ALfloat maxdist
, ratio
;
290 al_free(dec
->Samples
);
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
;
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.
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
;
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
;
353 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
355 maxdist
= maxf(maxdist
, conf
->Speakers
[i
].Distance
);
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
];
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
];
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
] *
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
] *
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
];
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
*
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
*
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
*
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
*
498 void bformatdec_process(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
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
])
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
));
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
,
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
];
549 for(chan
= 0;chan
< OutChannels
;chan
++)
551 if(!dec
->Enabled
[chan
])
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
));
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
,
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
)
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
598 for(i
= 0;i
< InChannels
;i
++)
600 /* First, split the first-order components into low and high frequency
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
];
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
)
635 void ambiup_reset(struct AmbiUpsampler
*ambiup
, const ALCdevice
*device
)
637 ALfloat gains
[8][MAX_OUTPUT_CHANNELS
];
641 ratio
= 400.0f
/ (ALfloat
)device
->Frequency
;
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
));
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
)
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
);