dep/cubeb: Update to dc511c6

This commit is contained in:
Connor McLaughlin
2022-08-05 17:28:17 +10:00
parent 06ecc50797
commit 8f45bf7f27
50 changed files with 5667 additions and 4813 deletions

View File

@ -9,6 +9,9 @@
#define NOMINMAX
#include "cubeb_mixer.h"
#include "cubeb-internal.h"
#include "cubeb_utils.h"
#include <algorithm>
#include <cassert>
#include <climits>
@ -16,67 +19,67 @@
#include <cstdlib>
#include <memory>
#include <type_traits>
#include "cubeb-internal.h"
#include "cubeb_mixer.h"
#include "cubeb_utils.h"
#ifndef FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
#endif
#define CHANNELS_MAX 32
#define FRONT_LEFT 0
#define FRONT_RIGHT 1
#define FRONT_CENTER 2
#define LOW_FREQUENCY 3
#define BACK_LEFT 4
#define BACK_RIGHT 5
#define FRONT_LEFT_OF_CENTER 6
#define FRONT_RIGHT_OF_CENTER 7
#define BACK_CENTER 8
#define SIDE_LEFT 9
#define SIDE_RIGHT 10
#define TOP_CENTER 11
#define TOP_FRONT_LEFT 12
#define TOP_FRONT_CENTER 13
#define TOP_FRONT_RIGHT 14
#define TOP_BACK_LEFT 15
#define TOP_BACK_CENTER 16
#define TOP_BACK_RIGHT 17
#define NUM_NAMED_CHANNELS 18
#define FRONT_LEFT 0
#define FRONT_RIGHT 1
#define FRONT_CENTER 2
#define LOW_FREQUENCY 3
#define BACK_LEFT 4
#define BACK_RIGHT 5
#define FRONT_LEFT_OF_CENTER 6
#define FRONT_RIGHT_OF_CENTER 7
#define BACK_CENTER 8
#define SIDE_LEFT 9
#define SIDE_RIGHT 10
#define TOP_CENTER 11
#define TOP_FRONT_LEFT 12
#define TOP_FRONT_CENTER 13
#define TOP_FRONT_RIGHT 14
#define TOP_BACK_LEFT 15
#define TOP_BACK_CENTER 16
#define TOP_BACK_RIGHT 17
#define NUM_NAMED_CHANNELS 18
#ifndef M_SQRT1_2
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#endif
#ifndef M_SQRT2
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
#endif
#define SQRT3_2 1.22474487139158904909 /* sqrt(3/2) */
#define SQRT3_2 1.22474487139158904909 /* sqrt(3/2) */
#define C30DB M_SQRT2
#define C15DB 1.189207115
#define C__0DB 1.0
#define C_15DB 0.840896415
#define C_30DB M_SQRT1_2
#define C_45DB 0.594603558
#define C_60DB 0.5
#define C30DB M_SQRT2
#define C15DB 1.189207115
#define C__0DB 1.0
#define C_15DB 0.840896415
#define C_30DB M_SQRT1_2
#define C_45DB 0.594603558
#define C_60DB 0.5
static cubeb_channel_layout
cubeb_channel_layout_check(cubeb_channel_layout l, uint32_t c)
{
if (l == CUBEB_LAYOUT_UNDEFINED) {
switch (c) {
case 1: return CUBEB_LAYOUT_MONO;
case 2: return CUBEB_LAYOUT_STEREO;
}
if (l == CUBEB_LAYOUT_UNDEFINED) {
switch (c) {
case 1:
return CUBEB_LAYOUT_MONO;
case 2:
return CUBEB_LAYOUT_STEREO;
}
return l;
}
return l;
}
unsigned int cubeb_channel_layout_nb_channels(cubeb_channel_layout x)
unsigned int
cubeb_channel_layout_nb_channels(cubeb_channel_layout x)
{
#if __GNUC__ || __clang__
return __builtin_popcount (x);
return __builtin_popcount(x);
#else
x -= (x >> 1) & 0x55555555;
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
@ -87,16 +90,12 @@ unsigned int cubeb_channel_layout_nb_channels(cubeb_channel_layout x)
}
struct MixerContext {
MixerContext(cubeb_sample_format f,
uint32_t in_channels,
cubeb_channel_layout in,
uint32_t out_channels,
MixerContext(cubeb_sample_format f, uint32_t in_channels,
cubeb_channel_layout in, uint32_t out_channels,
cubeb_channel_layout out)
: _format(f)
, _in_ch_layout(cubeb_channel_layout_check(in, in_channels))
, _out_ch_layout(cubeb_channel_layout_check(out, out_channels))
, _in_ch_count(in_channels)
, _out_ch_count(out_channels)
: _format(f), _in_ch_layout(cubeb_channel_layout_check(in, in_channels)),
_out_ch_layout(cubeb_channel_layout_check(out, out_channels)),
_in_ch_count(in_channels), _out_ch_count(out_channels)
{
if (in_channels != cubeb_channel_layout_nb_channels(in) ||
out_channels != cubeb_channel_layout_nb_channels(out)) {
@ -159,24 +158,30 @@ struct MixerContext {
int init();
const cubeb_sample_format _format;
const cubeb_channel_layout _in_ch_layout; ///< input channel layout
const cubeb_channel_layout _out_ch_layout; ///< output channel layout
const uint32_t _in_ch_count; ///< input channel count
const uint32_t _out_ch_count; ///< output channel count
const float _surround_mix_level = C_30DB; ///< surround mixing level
const float _center_mix_level = C_30DB; ///< center mixing level
const float _lfe_mix_level = 1; ///< LFE mixing level
double _matrix[CHANNELS_MAX][CHANNELS_MAX] = {{ 0 }}; ///< floating point rematrixing coefficients
float _matrix_flt[CHANNELS_MAX][CHANNELS_MAX] = {{ 0 }}; ///< single precision floating point rematrixing coefficients
int32_t _matrix32[CHANNELS_MAX][CHANNELS_MAX] = {{ 0 }}; ///< 17.15 fixed point rematrixing coefficients
uint8_t _matrix_ch[CHANNELS_MAX][CHANNELS_MAX+1] = {{ 0 }}; ///< Lists of input channels per output channel that have non zero rematrixing coefficients
bool _clipping = false; ///< Set to true if clipping detection is required
bool _valid = false; ///< Set to true if context is valid.
const cubeb_channel_layout _in_ch_layout; ///< input channel layout
const cubeb_channel_layout _out_ch_layout; ///< output channel layout
const uint32_t _in_ch_count; ///< input channel count
const uint32_t _out_ch_count; ///< output channel count
const float _surround_mix_level = C_30DB; ///< surround mixing level
const float _center_mix_level = C_30DB; ///< center mixing level
const float _lfe_mix_level = 1; ///< LFE mixing level
double _matrix[CHANNELS_MAX][CHANNELS_MAX] = {
{0}}; ///< floating point rematrixing coefficients
float _matrix_flt[CHANNELS_MAX][CHANNELS_MAX] = {
{0}}; ///< single precision floating point rematrixing coefficients
int32_t _matrix32[CHANNELS_MAX][CHANNELS_MAX] = {
{0}}; ///< 17.15 fixed point rematrixing coefficients
uint8_t _matrix_ch[CHANNELS_MAX][CHANNELS_MAX + 1] = {
{0}}; ///< Lists of input channels per output channel that have non zero
///< rematrixing coefficients
bool _clipping = false; ///< Set to true if clipping detection is required
bool _valid = false; ///< Set to true if context is valid.
};
int MixerContext::auto_matrix()
int
MixerContext::auto_matrix()
{
double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS] = { { 0 } };
double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS] = {{0}};
double maxcoef = 0;
float maxval;
@ -239,8 +244,7 @@ int MixerContext::auto_matrix()
matrix[FRONT_LEFT][BACK_CENTER] += _surround_mix_level * M_SQRT1_2;
matrix[FRONT_RIGHT][BACK_CENTER] += _surround_mix_level * M_SQRT1_2;
} else if (out_ch_layout & CHANNEL_FRONT_CENTER) {
matrix[FRONT_CENTER][BACK_CENTER] +=
_surround_mix_level * M_SQRT1_2;
matrix[FRONT_CENTER][BACK_CENTER] += _surround_mix_level * M_SQRT1_2;
}
}
if (unaccounted & CHANNEL_BACK_LEFT) {
@ -321,7 +325,7 @@ int MixerContext::auto_matrix()
_matrix[out_i][in_i] = matrix[i][j];
} else {
_matrix[out_i][in_i] =
i == j && (in_ch_layout & out_ch_layout & (1U << i));
i == j && (in_ch_layout & out_ch_layout & (1U << i));
}
sum += fabs(_matrix[out_i][in_i]);
in_i++;
@ -356,7 +360,8 @@ int MixerContext::auto_matrix()
return 0;
}
int MixerContext::init()
int
MixerContext::init()
{
int r = auto_matrix();
if (r) {
@ -398,22 +403,15 @@ int MixerContext::init()
return 0;
}
template<typename TYPE_SAMPLE, typename TYPE_COEFF, typename F>
template <typename TYPE_SAMPLE, typename TYPE_COEFF, typename F>
void
sum2(TYPE_SAMPLE * out,
uint32_t stride_out,
const TYPE_SAMPLE * in1,
const TYPE_SAMPLE * in2,
uint32_t stride_in,
TYPE_COEFF coeff1,
TYPE_COEFF coeff2,
F&& operand,
uint32_t frames)
sum2(TYPE_SAMPLE * out, uint32_t stride_out, const TYPE_SAMPLE * in1,
const TYPE_SAMPLE * in2, uint32_t stride_in, TYPE_COEFF coeff1,
TYPE_COEFF coeff2, F && operand, uint32_t frames)
{
static_assert(
std::is_same<TYPE_COEFF,
typename std::result_of<F(TYPE_COEFF)>::type>::value,
"function must return the same type as used by matrix_coeff");
std::is_same<TYPE_COEFF, decltype(operand(coeff1))>::value,
"function must return the same type as used by coeff1 and coeff2");
for (uint32_t i = 0; i < frames; i++) {
*out = operand(coeff1 * *in1 + coeff2 * *in2);
out += stride_out;
@ -422,20 +420,13 @@ sum2(TYPE_SAMPLE * out,
}
}
template<typename TYPE_SAMPLE, typename TYPE_COEFF, typename F>
template <typename TYPE_SAMPLE, typename TYPE_COEFF, typename F>
void
copy(TYPE_SAMPLE * out,
uint32_t stride_out,
const TYPE_SAMPLE * in,
uint32_t stride_in,
TYPE_COEFF coeff,
F&& operand,
uint32_t frames)
copy(TYPE_SAMPLE * out, uint32_t stride_out, const TYPE_SAMPLE * in,
uint32_t stride_in, TYPE_COEFF coeff, F && operand, uint32_t frames)
{
static_assert(
std::is_same<TYPE_COEFF,
typename std::result_of<F(TYPE_COEFF)>::type>::value,
"function must return the same type as used by matrix_coeff");
static_assert(std::is_same<TYPE_COEFF, decltype(operand(coeff))>::value,
"function must return the same type as used by coeff");
for (uint32_t i = 0; i < frames; i++) {
*out = operand(coeff * *in);
out += stride_out;
@ -444,74 +435,58 @@ copy(TYPE_SAMPLE * out,
}
template <typename TYPE, typename TYPE_COEFF, size_t COLS, typename F>
static int rematrix(const MixerContext * s, TYPE * aOut, const TYPE * aIn,
const TYPE_COEFF (&matrix_coeff)[COLS][COLS],
F&& aF, uint32_t frames)
static int
rematrix(const MixerContext * s, TYPE * aOut, const TYPE * aIn,
const TYPE_COEFF (&matrix_coeff)[COLS][COLS], F && aF, uint32_t frames)
{
static_assert(
std::is_same<TYPE_COEFF,
typename std::result_of<F(TYPE_COEFF)>::type>::value,
"function must return the same type as used by matrix_coeff");
std::is_same<TYPE_COEFF, decltype(aF(matrix_coeff[0][0]))>::value,
"function must return the same type as used by matrix_coeff");
for (uint32_t out_i = 0; out_i < s->_out_ch_count; out_i++) {
TYPE* out = aOut + out_i;
TYPE * out = aOut + out_i;
switch (s->_matrix_ch[out_i][0]) {
case 0:
for (uint32_t i = 0; i < frames; i++) {
out[i * s->_out_ch_count] = 0;
case 0:
for (uint32_t i = 0; i < frames; i++) {
out[i * s->_out_ch_count] = 0;
}
break;
case 1: {
int in_i = s->_matrix_ch[out_i][1];
copy(out, s->_out_ch_count, aIn + in_i, s->_in_ch_count,
matrix_coeff[out_i][in_i], aF, frames);
} break;
case 2:
sum2(out, s->_out_ch_count, aIn + s->_matrix_ch[out_i][1],
aIn + s->_matrix_ch[out_i][2], s->_in_ch_count,
matrix_coeff[out_i][s->_matrix_ch[out_i][1]],
matrix_coeff[out_i][s->_matrix_ch[out_i][2]], aF, frames);
break;
default:
for (uint32_t i = 0; i < frames; i++) {
TYPE_COEFF v = 0;
for (uint32_t j = 0; j < s->_matrix_ch[out_i][0]; j++) {
uint32_t in_i = s->_matrix_ch[out_i][1 + j];
v += *(aIn + in_i + i * s->_in_ch_count) * matrix_coeff[out_i][in_i];
}
break;
case 1: {
int in_i = s->_matrix_ch[out_i][1];
copy(out,
s->_out_ch_count,
aIn + in_i,
s->_in_ch_count,
matrix_coeff[out_i][in_i],
aF,
frames);
} break;
case 2:
sum2(out,
s->_out_ch_count,
aIn + s->_matrix_ch[out_i][1],
aIn + s->_matrix_ch[out_i][2],
s->_in_ch_count,
matrix_coeff[out_i][s->_matrix_ch[out_i][1]],
matrix_coeff[out_i][s->_matrix_ch[out_i][2]],
aF,
frames);
break;
default:
for (uint32_t i = 0; i < frames; i++) {
TYPE_COEFF v = 0;
for (uint32_t j = 0; j < s->_matrix_ch[out_i][0]; j++) {
uint32_t in_i = s->_matrix_ch[out_i][1 + j];
v +=
*(aIn + in_i + i * s->_in_ch_count) * matrix_coeff[out_i][in_i];
}
out[i * s->_out_ch_count] = aF(v);
}
break;
out[i * s->_out_ch_count] = aF(v);
}
break;
}
}
return 0;
}
struct cubeb_mixer
{
cubeb_mixer(cubeb_sample_format format,
uint32_t in_channels,
cubeb_channel_layout in_layout,
uint32_t out_channels,
struct cubeb_mixer {
cubeb_mixer(cubeb_sample_format format, uint32_t in_channels,
cubeb_channel_layout in_layout, uint32_t out_channels,
cubeb_channel_layout out_layout)
: _context(format, in_channels, in_layout, out_channels, out_layout)
: _context(format, in_channels, in_layout, out_channels, out_layout)
{
}
template<typename T>
void copy_and_trunc(size_t frames,
const T * input_buffer,
template <typename T>
void copy_and_trunc(size_t frames, const T * input_buffer,
T * output_buffer) const
{
if (_context._in_ch_count <= _context._out_ch_count) {
@ -545,11 +520,8 @@ struct cubeb_mixer
}
}
int mix(size_t frames,
const void * input_buffer,
size_t input_buffer_size,
void * output_buffer,
size_t output_buffer_size) const
int mix(size_t frames, const void * input_buffer, size_t input_buffer_size,
void * output_buffer, size_t output_buffer_size) const
{
if (frames <= 0 || _context._out_ch_count == 0) {
return 0;
@ -557,7 +529,7 @@ struct cubeb_mixer
// Check if output buffer is of sufficient size.
size_t size_read_needed =
frames * _context._in_ch_count * cubeb_sample_size(_context._format);
frames * _context._in_ch_count * cubeb_sample_size(_context._format);
if (input_buffer_size < size_read_needed) {
// We don't have enough data to read!
return -1;
@ -571,58 +543,46 @@ struct cubeb_mixer
// The channel layouts were invalid or unsupported, instead we will simply
// either drop the extra channels, or fill with silence the missing ones
if (_context._format == CUBEB_SAMPLE_FLOAT32NE) {
copy_and_trunc(frames,
static_cast<const float*>(input_buffer),
static_cast<float*>(output_buffer));
copy_and_trunc(frames, static_cast<const float *>(input_buffer),
static_cast<float *>(output_buffer));
} else {
assert(_context._format == CUBEB_SAMPLE_S16NE);
copy_and_trunc(frames,
static_cast<const int16_t*>(input_buffer),
reinterpret_cast<int16_t*>(output_buffer));
copy_and_trunc(frames, static_cast<const int16_t *>(input_buffer),
reinterpret_cast<int16_t *>(output_buffer));
}
return 0;
}
switch (_context._format)
{
case CUBEB_SAMPLE_FLOAT32NE: {
auto f = [](float x) { return x; };
return rematrix(&_context,
static_cast<float*>(output_buffer),
static_cast<const float*>(input_buffer),
_context._matrix_flt,
f,
frames);
switch (_context._format) {
case CUBEB_SAMPLE_FLOAT32NE: {
auto f = [](float x) { return x; };
return rematrix(&_context, static_cast<float *>(output_buffer),
static_cast<const float *>(input_buffer),
_context._matrix_flt, f, frames);
}
case CUBEB_SAMPLE_S16NE:
if (_context._clipping) {
auto f = [](int x) {
int y = (x + 16384) >> 15;
// clip the signed integer value into the -32768,32767 range.
if ((y + 0x8000U) & ~0xFFFF) {
return (y >> 31) ^ 0x7FFF;
}
return y;
};
return rematrix(&_context, static_cast<int16_t *>(output_buffer),
static_cast<const int16_t *>(input_buffer),
_context._matrix32, f, frames);
} else {
auto f = [](int x) { return (x + 16384) >> 15; };
return rematrix(&_context, static_cast<int16_t *>(output_buffer),
static_cast<const int16_t *>(input_buffer),
_context._matrix32, f, frames);
}
case CUBEB_SAMPLE_S16NE:
if (_context._clipping) {
auto f = [](int x) {
int y = (x + 16384) >> 15;
// clip the signed integer value into the -32768,32767 range.
if ((y + 0x8000U) & ~0xFFFF) {
return (y >> 31) ^ 0x7FFF;
}
return y;
};
return rematrix(&_context,
static_cast<int16_t*>(output_buffer),
static_cast<const int16_t*>(input_buffer),
_context._matrix32,
f,
frames);
} else {
auto f = [](int x) { return (x + 16384) >> 15; };
return rematrix(&_context,
static_cast<int16_t*>(output_buffer),
static_cast<const int16_t*>(input_buffer),
_context._matrix32,
f,
frames);
}
break;
default:
assert(false);
break;
break;
default:
assert(false);
break;
}
return -1;
@ -636,28 +596,26 @@ struct cubeb_mixer
MixerContext _context;
};
cubeb_mixer* cubeb_mixer_create(cubeb_sample_format format,
uint32_t in_channels,
cubeb_channel_layout in_layout,
uint32_t out_channels,
cubeb_channel_layout out_layout)
cubeb_mixer *
cubeb_mixer_create(cubeb_sample_format format, uint32_t in_channels,
cubeb_channel_layout in_layout, uint32_t out_channels,
cubeb_channel_layout out_layout)
{
return new cubeb_mixer(
format, in_channels, in_layout, out_channels, out_layout);
return new cubeb_mixer(format, in_channels, in_layout, out_channels,
out_layout);
}
void cubeb_mixer_destroy(cubeb_mixer * mixer)
void
cubeb_mixer_destroy(cubeb_mixer * mixer)
{
delete mixer;
}
int cubeb_mixer_mix(cubeb_mixer * mixer,
size_t frames,
const void * input_buffer,
size_t input_buffer_size,
void * output_buffer,
size_t output_buffer_size)
int
cubeb_mixer_mix(cubeb_mixer * mixer, size_t frames, const void * input_buffer,
size_t input_buffer_size, void * output_buffer,
size_t output_buffer_size)
{
return mixer->mix(
frames, input_buffer, input_buffer_size, output_buffer, output_buffer_size);
return mixer->mix(frames, input_buffer, input_buffer_size, output_buffer,
output_buffer_size);
}