summaryrefslogtreecommitdiffstats
path: root/src/converter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/converter.c')
-rw-r--r--src/converter.c158
1 files changed, 81 insertions, 77 deletions
diff --git a/src/converter.c b/src/converter.c
index 3b146ce..c5283f6 100644
--- a/src/converter.c
+++ b/src/converter.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <math.h>
#include <string.h>
@@ -9,7 +13,7 @@
#include "common.h"
#include "format.h"
#include "volscale.h"
-#include "byteswap.h"
+#include "bswap.h"
#include "zero.h"
#include "add.h"
#include "bbuffer.h"
@@ -36,21 +40,21 @@ static int native_pcm_format_resample(sa_pcm_format_t f) {
}
static sa_pcm_format_t byteswap_fix(sa_pcm_format_t f) {
-
+
switch (f) {
case SA_PCM_FORMAT_U8:
case SA_PCM_FORMAT_ULAW:
case SA_PCM_FORMAT_ALAW:
return f;
-
+
case SA_PCM_FORMAT_S16_NE:
case SA_PCM_FORMAT_S16_RE:
return SA_PCM_FORMAT_S16_NE;
-
+
case SA_PCM_FORMAT_S24_NE:
case SA_PCM_FORMAT_S24_RE:
return SA_PCM_FORMAT_S24_NE;
-
+
case SA_PCM_FORMAT_S32_NE:
case SA_PCM_FORMAT_S32_RE:
return SA_PCM_FORMAT_S32_NE;
@@ -67,12 +71,12 @@ static sa_pcm_format_t byteswap_fix(sa_pcm_format_t f) {
}
static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
-
+
switch (a) {
case SA_PCM_FORMAT_U8:
case SA_PCM_FORMAT_ULAW:
case SA_PCM_FORMAT_ALAW:
-
+
switch (b) {
case SA_PCM_FORMAT_U8:
return SA_PCM_FORMAT_U8;
@@ -88,7 +92,7 @@ static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
case SA_PCM_FORMAT_S32_LE:
case SA_PCM_FORMAT_S32_BE:
return SA_PCM_FORMAT_S32_NE;
-
+
case SA_PCM_FORMAT_FLOAT32_LE:
case SA_PCM_FORMAT_FLOAT32_BE:
return SA_PCM_FORMAT_FLOAT32_NE;
@@ -98,7 +102,7 @@ static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
}
break;
-
+
case SA_PCM_FORMAT_S16_LE:
case SA_PCM_FORMAT_S16_BE:
@@ -115,7 +119,7 @@ static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
case SA_PCM_FORMAT_S32_LE:
case SA_PCM_FORMAT_S32_BE:
return SA_PCM_FORMAT_S32_NE;
-
+
case SA_PCM_FORMAT_FLOAT32_LE:
case SA_PCM_FORMAT_FLOAT32_BE:
return SA_PCM_FORMAT_FLOAT32_NE;
@@ -124,7 +128,7 @@ static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
;
}
break;
-
+
case SA_PCM_FORMAT_S24_LE:
case SA_PCM_FORMAT_S24_BE:
case SA_PCM_FORMAT_S32_LE:
@@ -141,7 +145,7 @@ static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
case SA_PCM_FORMAT_S32_LE:
case SA_PCM_FORMAT_S32_BE:
return SA_PCM_FORMAT_S32_NE;
-
+
case SA_PCM_FORMAT_FLOAT32_LE:
case SA_PCM_FORMAT_FLOAT32_BE:
return SA_PCM_FORMAT_FLOAT32_NE;
@@ -150,7 +154,7 @@ static sa_pcm_format_t get_work_format(sa_pcm_format_t a, sa_pcm_format_t b) {
;
}
break;
-
+
case SA_PCM_FORMAT_FLOAT32_LE:
case SA_PCM_FORMAT_FLOAT32_BE:
return SA_PCM_FORMAT_FLOAT32_NE;
@@ -169,12 +173,12 @@ static sa_pcm_format_t fix_work_format_for_resample(sa_pcm_format_t f) {
case SA_PCM_FORMAT_S16_NE:
return SA_PCM_FORMAT_S16_NE;
break;
-
+
case SA_PCM_FORMAT_S32_NE:
case SA_PCM_FORMAT_FLOAT32_NE:
return SA_PCM_FORMAT_FLOAT32_NE;
break;
-
+
default:
;
}
@@ -190,7 +194,7 @@ int sa_converter_init(
unsigned u, t;
int resample_required;
-
+
sa_assert(c);
sa_assert(from);
sa_assert(to);
@@ -211,26 +215,26 @@ int sa_converter_init(
for (u = 0; u < to->nchannels; u++) {
unsigned k = 0;
-
+
for (t = 0; t < from->nchannels; t++) {
if (from->channel_map[u] == to->channel_map[t]) {
if (u != t)
c->remap_required = 1;
-
+
c->channel_map_table[u * (from->nchannels+1) + k++] += t;
}
}
if (k > 1)
c->sum_required = 1;
-
+
c->channel_map_table[k] = (unsigned) -1;
}
if (c->from_nchannels != c->to_nchannels)
- c->remap_required = 1;
-
+ c->remap_required = 1;
+
resample_required =
from->rate != to->rate ||
dynamic_rate_enabled;
@@ -238,7 +242,7 @@ int sa_converter_init(
c->work_pcm_format = get_work_format(from->format, to->format);
if (resample_required)
c->work_pcm_format = fix_work_format_for_resample(c->work_pcm_format);
-
+
sa_assert(native_pcm_format_process(c->work_pcm_format));
sa_assert(!resample_required || native_pcm_format_resample(c->work_pcm_format));
@@ -253,31 +257,31 @@ int sa_converter_init(
c->pre_format_func = sa_get_format_func(byteswap_fix(from->format), c->work_pcm_format);
sa_assert(c->pre_format_func);
}
-
+
c->volscale_func = sa_get_volscale_func(c->work_pcm_format);
sa_assert(c->volscale_func);
-
+
c->zero_func = sa_get_zero_func(c->work_pcm_format);
sa_assert(c->zero_func);
-
+
c->add_func = sa_get_add_func(c->work_pcm_format);
sa_assert(c->add_func);
if (resample_required) {
c->resample_func = sa_get_resample_func(c->work_pcm_format);
sa_assert(c->resample_func);
- }
+ }
if (c->work_pcm_format != byteswap_fix(to->format)) {
c->post_format_func = sa_get_format_func(c->work_pcm_format, byteswap_fix(to->format));
sa_assert(c->post_format_func);
}
-
+
c->post_byteswap_func = sa_get_byteswap_func(to->format);
c->interleave_func = sa_get_interleave_func(to->format);
sa_assert(c->interleave_func);
-
+
/* Initialize resampler */
if (resample_required) {
@@ -309,7 +313,7 @@ int sa_converter_init(
c->no_volume = 1;
/* Initialize bounce buffers */
-
+
if (sa_bbuffer_init(&c->bb_pre_byteswap, c->from_nchannels, c->from_sample_size) < 0)
goto fail;
if (sa_bbuffer_init(&c->bb_pre_format, c->from_nchannels, c->work_sample_size) < 0)
@@ -328,7 +332,7 @@ int sa_converter_init(
goto fail;
if (sa_bbuffer_init(&c->bb_tmp, 1, 1) < 0)
goto fail;
-
+
return 0;
fail:
@@ -341,7 +345,7 @@ void sa_converter_done(sa_converter_t *c) {
sa_assert(c);
sa_free(c->channel_map_table);
-
+
sa_free(c->from_process_data);
sa_free(c->to_process_data);
sa_free(c->from_stride);
@@ -369,7 +373,7 @@ void sa_converter_done(sa_converter_t *c) {
void* sa_converter_get_zero_buffer(sa_converter_t *c, size_t size) {
void *b;
-
+
sa_assert(c);
sa_assert(size > 0);
@@ -382,7 +386,7 @@ void* sa_converter_get_zero_buffer(sa_converter_t *c, size_t size) {
return NULL;
c->zero_func(b, c->work_sample_size, size);
- return c->zero_func;
+ return c->zero_buffer;
}
int sa_converter_go(
@@ -390,13 +394,13 @@ int sa_converter_go(
const void *const src[], const size_t sstr[], int sinterleave,
void **dst[], size_t *dstr[], int dinterleave,
size_t *size) {
-
+
size_t* stride;
void** process_data;
int is_bounce;
int interleave;
unsigned i;
-
+
sa_assert(c);
is_bounce = 0;
@@ -404,7 +408,7 @@ int sa_converter_go(
process_data = (void**) src;
interleave = !!sinterleave;
dinterleave = !!dinterleave;
-
+
if (c->no_volume &&
!c->remap_required &&
!c->resample_func &&
@@ -414,18 +418,18 @@ int sa_converter_go(
goto do_interleave;
}
-
+
if (c->pre_byteswap_func) {
size_t k;
-
+
k = dinterleave ? c->from_sample_size*c->from_nchannels : c->from_sample_size;
-
+
for (i = 0; i < c->from_nchannels; i++) {
void *b;
if (!(b = sa_bbuffer_get(&c->bb_pre_byteswap, i, *size, dinterleave)))
return SA_ERROR_OOM;
-
+
c->pre_byteswap_func(b, k, process_data[i], stride[i], *size);
c->from_process_data[i] = b;
c->from_stride[i] = k;
@@ -436,7 +440,7 @@ int sa_converter_go(
interleave = dinterleave;
is_bounce = 1;
}
-
+
if (c->pre_format_func) {
if (is_bounce && c->from_sample_size == c->to_sample_size) {
@@ -446,24 +450,24 @@ int sa_converter_go(
for (i = 0; i < c->from_nchannels; i++)
c->pre_format_func(&c->bb_tmp, process_data[i], stride[i], process_data[i], stride[i], *size);
-
+
} else {
size_t k, new_size;
-
+
new_size = *size / c->from_sample_size * c->work_sample_size;
k = dinterleave ? c->work_sample_size*c->from_nchannels : c->work_sample_size;
-
+
for (i = 0; i < c->from_nchannels; i++) {
void *b;
-
+
if (!(b = sa_bbuffer_get(&c->bb_pre_format, i, new_size, dinterleave)))
return SA_ERROR_OOM;
-
+
c->pre_format_func(&c->bb_tmp, b, k, process_data[i], stride[i], *size);
c->from_process_data[i] = b;
c->from_stride[i] = k;
}
-
+
process_data = c->from_process_data;
stride = c->from_stride;
*size = new_size;
@@ -480,7 +484,7 @@ int sa_converter_go(
/* The data to process is already in a bounce buffer, we
* can do this in-place */
-
+
for (i = 0; i < c->from_nchannels; i++);
c->volscale_func(process_data[i], stride[i], process_data[i], stride[i], c->volume_factor[i], c->volume_divisor[i], *size);
@@ -491,15 +495,15 @@ int sa_converter_go(
for (i = 0; i < c->from_nchannels; i++) {
void *b;
-
+
if (!(b = sa_bbuffer_get(&c->bb_volscale, i, *size, dinterleave)))
return SA_ERROR_OOM;
-
+
c->volscale_func(b, k, process_data[i], stride[i], c->volume_factor[i], c->volume_divisor[i], *size);
c->from_process_data[i] = b;
c->from_stride[i] = k;
}
-
+
process_data = c->from_process_data;
stride = c->from_stride;
interleave = dinterleave;
@@ -516,7 +520,7 @@ int sa_converter_go(
for (i = 0; i < c->to_nchannels; i++) {
void *b;
int *p = &c->channel_map_table[i * (c->from_nchannels+1)];
-
+
if (p[0] == -1) {
/* We have to write silence to this channel */
@@ -536,8 +540,8 @@ int sa_converter_go(
need_proper_interleave = 1;
} else {
int j;
-
- /* We have to mix two or more channels */
+
+ /* We have to mix two or more channels */
if (!(b = sa_bbuffer_get(&c->bb_remap, i, *size, dinterleave)))
return SA_ERROR_OOM;
@@ -546,7 +550,7 @@ int sa_converter_go(
for (j = 2; p[j] != -1; j++)
c->add_func(b, k, b, k, process_data[p[j]], stride[p[j]], *size);
-
+
c->to_process_data[i] = b;
c->to_stride[i] = k;
}
@@ -565,7 +569,7 @@ int sa_converter_go(
k = dinterleave ? c->work_sample_size*c->to_nchannels : c->work_sample_size;
new_size = (size_t) (((((uint64_t) *size+c->work_sample_size-1)/c->work_sample_size)*c->to_rate)/c->from_rate+1)*c->work_sample_size; /* FIXME */
-
+
for (i = 0; i < c->to_nchannels; i++) {
void *b;
@@ -590,7 +594,7 @@ int sa_converter_go(
/* The data to process is already in a bounce buffer, we
* can do this in-place */
-
+
for (i = 0; i < c->to_nchannels; i++)
c->post_format_func(&c->bb_tmp, process_data[i], stride[i], process_data[i], stride[i], *size);
@@ -599,18 +603,18 @@ int sa_converter_go(
k = dinterleave ? c->to_sample_size*c->to_nchannels : c->to_sample_size;
new_size = *size / c->work_sample_size * c->to_sample_size;
-
+
for (i = 0; i < c->to_nchannels; i++) {
void *b;
-
+
if (!(b = sa_bbuffer_get(&c->bb_post_format, i, new_size, dinterleave)))
return SA_ERROR_OOM;
-
+
c->post_format_func(&c->bb_tmp, b, k, process_data[i], stride[i], *size);
c->to_process_data[i] = b;
c->to_stride[i] = k;
}
-
+
process_data = c->to_process_data;
stride = c->to_stride;
*size = new_size;
@@ -618,14 +622,14 @@ int sa_converter_go(
is_bounce = 1;
}
}
-
+
if (c->post_byteswap_func) {
if (is_bounce) {
/* The data to process is already in a bounce buffer, we
* can do this in-place */
-
+
for (i = 0; i < c->to_nchannels; i++)
c->post_byteswap_func(process_data[i], stride[i], process_data[i], stride[i], *size);
@@ -633,15 +637,15 @@ int sa_converter_go(
size_t k;
k = dinterleave ? c->to_sample_size*c->to_nchannels : c->to_sample_size;
-
+
for (i = 0; i < c->to_nchannels; i++) {
void *b;
-
+
if (!(b = sa_bbuffer_get(&c->bb_post_byteswap, i, *size, dinterleave)))
return SA_ERROR_OOM;
-
+
c->post_byteswap_func(b, k, process_data[i], stride[i], *size);
-
+
c->to_process_data[i] = b;
c->to_stride[i] = k;
}
@@ -654,7 +658,7 @@ int sa_converter_go(
}
do_interleave:
-
+
if (interleave != dinterleave) {
size_t k;
@@ -662,16 +666,16 @@ do_interleave:
for (i = 0; i < c->to_nchannels; i++) {
void *b;
-
+
if (!(b = sa_bbuffer_get(&c->bb_interleave, i, *size, dinterleave)))
return SA_ERROR_OOM;
-
+
c->interleave_func(b, k, process_data[i], stride[i], *size);
-
+
c->to_process_data[i] = b;
c->to_stride[i] = k;
}
-
+
process_data = c->to_process_data;
stride = c->to_stride;
interleave = dinterleave;
@@ -687,7 +691,7 @@ do_interleave:
void sa_converter_set_volume(sa_converter_t *c, const int32_t vol[]) {
unsigned i;
int no_volume = 1;
-
+
sa_assert(c);
for (i = 0; i < c->from_nchannels; i++) {
@@ -702,12 +706,12 @@ void sa_converter_set_volume(sa_converter_t *c, const int32_t vol[]) {
no_volume = 0;
} else {
float f = powf(10.0, (float) vol[i] / 2000);
-
+
sa_continued_fraction(f, 0x7FFF, &num, &denom);
-
+
if (num != 1 || denom != 1)
no_volume = 0;
-
+
c->volume_factor[i] = (int32_t) num;
c->volume_divisor[i] = (int32_t) denom;
}
@@ -718,7 +722,7 @@ void sa_converter_set_volume(sa_converter_t *c, const int32_t vol[]) {
int sa_converter_go_interleaved(
sa_converter_t *c,
- const void *const data,
+ const void *const data,
void **dst[], size_t *dstr[], int dinterleave,
size_t *size) {