#include <string.h>
#include <pulse/sample.h>
+#include <pulse/volume.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include "remap.h"
-static void remap_mono_to_stereo_c (pa_remap_t *m, void *dst, const void *src, unsigned n) {
+static void remap_mono_to_stereo_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
unsigned i;
- switch (*m->format) {
- case PA_SAMPLE_FLOAT32NE:
- {
- float *d, *s;
+ for (i = n >> 2; i; i--) {
+ dst[0] = dst[1] = src[0];
+ dst[2] = dst[3] = src[1];
+ dst[4] = dst[5] = src[2];
+ dst[6] = dst[7] = src[3];
+ src += 4;
+ dst += 8;
+ }
+ for (i = n & 3; i; i--) {
+ dst[0] = dst[1] = src[0];
+ src++;
+ dst += 2;
+ }
+}
- d = (float *) dst;
- s = (float *) src;
+static void remap_mono_to_stereo_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
+ unsigned i;
- for (i = n >> 2; i; i--) {
- d[0] = d[1] = s[0];
- d[2] = d[3] = s[1];
- d[4] = d[5] = s[2];
- d[6] = d[7] = s[3];
- s += 4;
- d += 8;
- }
- for (i = n & 3; i; i--) {
- d[0] = d[1] = s[0];
- s++;
- d += 2;
- }
- break;
- }
- case PA_SAMPLE_S16NE:
- {
+ for (i = n >> 2; i; i--) {
+ dst[0] = dst[1] = src[0];
+ dst[2] = dst[3] = src[1];
+ dst[4] = dst[5] = src[2];
+ dst[6] = dst[7] = src[3];
+ src += 4;
+ dst += 8;
+ }
+ for (i = n & 3; i; i--) {
+ dst[0] = dst[1] = src[0];
+ src++;
+ dst += 2;
+ }
+}
+
+static void remap_channels_matrix_s16ne_c(pa_remap_t *m, void *dst, const void *src, unsigned n) {
+ unsigned oc, ic, i;
+ unsigned n_ic, n_oc;
+
+ n_ic = m->i_ss.channels;
+ n_oc = m->o_ss.channels;
+
+ memset(dst, 0, n * sizeof(int16_t) * n_oc);
+
+ for (oc = 0; oc < n_oc; oc++) {
+
+ for (ic = 0; ic < n_ic; ic++) {
int16_t *d, *s;
+ int32_t vol;
- d = (int16_t *) dst;
- s = (int16_t *) src;
+ vol = m->map_table_i[oc][ic];
- for (i = n >> 2; i; i--) {
- d[0] = d[1] = s[0];
- d[2] = d[3] = s[1];
- d[4] = d[5] = s[2];
- d[6] = d[7] = s[3];
- s += 4;
- d += 8;
- }
- for (i = n & 3; i; i--) {
- d[0] = d[1] = s[0];
- s++;
- d += 2;
+ if (vol <= 0)
+ continue;
+
+ d = (int16_t *)dst + oc;
+ s = (int16_t *)src + ic;
+
+ if (vol >= 0x10000) {
+ for (i = n; i > 0; i--, s += n_ic, d += n_oc)
+ *d += *s;
+ } else {
+ for (i = n; i > 0; i--, s += n_ic, d += n_oc)
+ *d += (int16_t) (((int32_t)*s * vol) >> 16);
}
- break;
}
- default:
- pa_assert_not_reached();
}
}
-static void remap_channels_matrix_c (pa_remap_t *m, void *dst, const void *src, unsigned n) {
+static void remap_channels_matrix_float32ne_c(pa_remap_t *m, void *dst, const void *src, unsigned n) {
unsigned oc, ic, i;
unsigned n_ic, n_oc;
- n_ic = m->i_ss->channels;
- n_oc = m->o_ss->channels;
-
- switch (*m->format) {
- case PA_SAMPLE_FLOAT32NE:
- {
- float *d, *s;
+ n_ic = m->i_ss.channels;
+ n_oc = m->o_ss.channels;
- memset(dst, 0, n * sizeof (float) * n_oc);
+ memset(dst, 0, n * sizeof(float) * n_oc);
- for (oc = 0; oc < n_oc; oc++) {
+ for (oc = 0; oc < n_oc; oc++) {
- for (ic = 0; ic < n_ic; ic++) {
- float vol;
+ for (ic = 0; ic < n_ic; ic++) {
+ float *d, *s;
+ float vol;
- vol = m->map_table_f[oc][ic];
+ vol = m->map_table_f[oc][ic];
- if (vol <= 0.0)
- continue;
+ if (vol <= 0.0f)
+ continue;
- d = (float *)dst + oc;
- s = (float *)src + ic;
+ d = (float *)dst + oc;
+ s = (float *)src + ic;
- if (vol >= 1.0) {
- for (i = n; i > 0; i--, s += n_ic, d += n_oc)
- *d += *s;
- } else {
- for (i = n; i > 0; i--, s += n_ic, d += n_oc)
- *d += *s * vol;
- }
- }
+ if (vol >= 1.0f) {
+ for (i = n; i > 0; i--, s += n_ic, d += n_oc)
+ *d += *s;
+ } else {
+ for (i = n; i > 0; i--, s += n_ic, d += n_oc)
+ *d += *s * vol;
}
-
- break;
}
- case PA_SAMPLE_S16NE:
- {
- int16_t *d, *s;
+ }
+}
- memset(dst, 0, n * sizeof (int16_t) * n_oc);
+bool pa_setup_remap_arrange(const pa_remap_t *m, int8_t arrange[PA_CHANNELS_MAX]) {
+ unsigned ic, oc;
+ unsigned n_ic, n_oc;
- for (oc = 0; oc < n_oc; oc++) {
+ pa_assert(m);
- for (ic = 0; ic < n_ic; ic++) {
- int32_t vol;
+ n_ic = m->i_ss.channels;
+ n_oc = m->o_ss.channels;
- vol = m->map_table_i[oc][ic];
+ for (oc = 0; oc < n_oc; oc++) {
+ arrange[oc] = -1;
+ for (ic = 0; ic < n_ic; ic++) {
+ int32_t vol = m->map_table_i[oc][ic];
- if (vol <= 0)
- continue;
+ /* input channel is not used */
+ if (vol == 0)
+ continue;
- d = (int16_t *)dst + oc;
- s = (int16_t *)src + ic;
+ /* if mixing this channel, we cannot just rearrange */
+ if (vol != 0x10000 || arrange[oc] >= 0)
+ return false;
- if (vol >= 0x10000) {
- for (i = n; i > 0; i--, s += n_ic, d += n_oc)
- *d += *s;
- } else {
- for (i = n; i > 0; i--, s += n_ic, d += n_oc)
- *d += (int16_t) (((int32_t)*s * vol) >> 16);
- }
- }
- }
- break;
+ arrange[oc] = ic;
}
- default:
- pa_assert_not_reached();
}
+
+ return true;
+}
+
+void pa_set_remap_func(pa_remap_t *m, pa_do_remap_func_t func_s16,
+ pa_do_remap_func_t func_float) {
+
+ pa_assert(m);
+
+ if (m->format == PA_SAMPLE_S16NE)
+ m->do_remap = func_s16;
+ else if (m->format == PA_SAMPLE_FLOAT32NE)
+ m->do_remap = func_float;
+ else
+ pa_assert_not_reached();
}
/* set the function that will execute the remapping based on the matrices */
-static void init_remap_c (pa_remap_t *m) {
+static void init_remap_c(pa_remap_t *m) {
unsigned n_oc, n_ic;
- n_oc = m->o_ss->channels;
- n_ic = m->i_ss->channels;
+ n_oc = m->o_ss.channels;
+ n_ic = m->i_ss.channels;
/* find some common channel remappings, fall back to full matrix operation. */
if (n_ic == 1 && n_oc == 2 &&
- m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
- m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_c;
+ m->map_table_i[0][0] == 0x10000 && m->map_table_i[1][0] == 0x10000) {
+
pa_log_info("Using mono to stereo remapping");
+ pa_set_remap_func(m, (pa_do_remap_func_t) remap_mono_to_stereo_s16ne_c,
+ (pa_do_remap_func_t) remap_mono_to_stereo_float32ne_c);
} else {
- m->do_remap = (pa_do_remap_func_t) remap_channels_matrix_c;
pa_log_info("Using generic matrix remapping");
+
+ pa_set_remap_func(m, remap_channels_matrix_s16ne_c, remap_channels_matrix_float32ne_c);
}
}
-
/* default C implementation */
-static pa_init_remap_func_t remap_func = init_remap_c;
+static pa_init_remap_func_t init_remap_func = init_remap_c;
+
+void pa_init_remap_func(pa_remap_t *m) {
+ pa_assert(init_remap_func);
-void pa_init_remap (pa_remap_t *m) {
- pa_assert (remap_func);
+ m->do_remap = NULL;
- /* just call the installed remap init functions */
- remap_func (m);
+ /* call the installed remap init function */
+ init_remap_func(m);
if (m->do_remap == NULL) {
- /* nothing was installed, fallback to C versions */
- init_remap_c (m);
+ /* nothing was installed, fallback to C version */
+ init_remap_c(m);
}
}
pa_init_remap_func_t pa_get_init_remap_func(void) {
- return remap_func;
+ return init_remap_func;
}
void pa_set_init_remap_func(pa_init_remap_func_t func) {
- remap_func = func;
+ init_remap_func = func;
}