diff options
Diffstat (limited to 'cras/src/server/cras_fmt_conv_ops.c')
-rw-r--r-- | cras/src/server/cras_fmt_conv_ops.c | 69 |
1 files changed, 59 insertions, 10 deletions
diff --git a/cras/src/server/cras_fmt_conv_ops.c b/cras/src/server/cras_fmt_conv_ops.c index 87358af2..a306d216 100644 --- a/cras/src/server/cras_fmt_conv_ops.c +++ b/cras/src/server/cras_fmt_conv_ops.c @@ -235,20 +235,69 @@ size_t s16_51_to_stereo(const uint8_t *_in, size_t in_frames, uint8_t *_out) int16_t *out = (int16_t *)_out; static const unsigned int left_idx = 0; static const unsigned int right_idx = 1; - /* static const unsigned int left_surround_idx = 2; */ - /* static const unsigned int right_surround_idx = 3; */ - static const unsigned int center_idx = 4; - /* static const unsigned int lfe_idx = 5; */ - size_t i; + static const unsigned int center_idx = 2; + /* static const unsigned int lfe_idx = 3; */ + /* static const unsigned int left_surround_idx = 4; */ + /* static const unsigned int right_surround_idx = 5; */ + size_t i; + int16_t half_center; + /* Use the normalized_factor from the left channel = 1 / (|1| + |0.707|) + * to prevent mixing overflow. + */ + const float normalized_factor = 0.585; for (i = 0; i < in_frames; i++) { - unsigned int half_center; - - half_center = in[6 * i + center_idx] / 2; + half_center = + in[6 * i + center_idx] * 0.707 * normalized_factor; out[2 * i + left_idx] = - s16_add_and_clip(in[6 * i + left_idx], half_center); + in[6 * i + left_idx] * normalized_factor + half_center; out[2 * i + right_idx] = - s16_add_and_clip(in[6 * i + right_idx], half_center); + in[6 * i + right_idx] * normalized_factor + half_center; + } + return in_frames; +} + +/* + * Channel converter: 5.1 surround to quad (front L/R, rear L/R). + * + * The out buffer can have room for just quad samples. This convert function + * is used as the default behavior when channel layout is not set from the + * client side. + */ +size_t s16_51_to_quad(const uint8_t *_in, size_t in_frames, uint8_t *_out) +{ + const int16_t *in = (const int16_t *)_in; + int16_t *out = (int16_t *)_out; + static const unsigned int l_quad = 0; + static const unsigned int r_quad = 1; + static const unsigned int rl_quad = 2; + static const unsigned int rr_quad = 3; + + static const unsigned int l_51 = 0; + static const unsigned int r_51 = 1; + static const unsigned int center_51 = 2; + static const unsigned int lfe_51 = 3; + static const unsigned int rl_51 = 4; + static const unsigned int rr_51 = 5; + + /* Use normalized_factor from the left channel = 1 / (|1| + |0.707| + |0.5|) + * to prevent overflow. */ + const float normalized_factor = 0.453; + size_t i; + for (i = 0; i < in_frames; i++) { + int16_t half_center; + int16_t lfe; + + half_center = in[6 * i + center_51] * 0.707 * normalized_factor; + lfe = in[6 * i + lfe_51] * 0.5 * normalized_factor; + out[4 * i + l_quad] = normalized_factor * in[6 * i + l_51] + + half_center + lfe; + out[4 * i + r_quad] = normalized_factor * in[6 * i + r_51] + + half_center + lfe; + out[4 * i + rl_quad] = + normalized_factor * in[6 * i + rl_51] + lfe; + out[4 * i + rr_quad] = + normalized_factor * in[6 * i + rr_51] + lfe; } return in_frames; } |