summaryrefslogtreecommitdiff
path: root/cras/src/server/cras_fmt_conv_ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/server/cras_fmt_conv_ops.c')
-rw-r--r--cras/src/server/cras_fmt_conv_ops.c69
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;
}