summaryrefslogtreecommitdiffstats
path: root/converter.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-10-01 20:16:28 +0000
committerLennart Poettering <lennart@poettering.net>2007-10-01 20:16:28 +0000
commit7d83e5c7816b5e343695a75ba58b32dbe1be969a (patch)
treebfd1dfc9b7c8f4a2aaf66c1b30e78355dee8c88a /converter.c
parent762196328ab7e60f1d2908fd5a337d2ca99726dd (diff)
move all sources down to a seperate src/ tree
git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@34 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce
Diffstat (limited to 'converter.c')
-rw-r--r--converter.c743
1 files changed, 0 insertions, 743 deletions
diff --git a/converter.c b/converter.c
deleted file mode 100644
index 3b146ce..0000000
--- a/converter.c
+++ /dev/null
@@ -1,743 +0,0 @@
-#include <math.h>
-#include <string.h>
-
-#include "speex/speex_resampler.h"
-
-#include "converter.h"
-#include "sydney.h"
-#include "macro.h"
-#include "common.h"
-#include "format.h"
-#include "volscale.h"
-#include "byteswap.h"
-#include "zero.h"
-#include "add.h"
-#include "bbuffer.h"
-#include "continued-fraction.h"
-#include "malloc.h"
-#include "resample.h"
-
-/* Steps: byteswap -> convert -> volscale -> remap -> resample -> convert -> byteswap -> interleave */
-
-/* Sample formats we know to process natively */
-static int native_pcm_format_process(sa_pcm_format_t f) {
- return
- f == SA_PCM_FORMAT_U8 ||
- f == SA_PCM_FORMAT_S16_NE ||
- f == SA_PCM_FORMAT_S32_NE ||
- f == SA_PCM_FORMAT_FLOAT32_NE;
-}
-
-/* Sample formats we know to resample natively */
-static int native_pcm_format_resample(sa_pcm_format_t f) {
- return
- f == SA_PCM_FORMAT_S16_NE ||
- f == SA_PCM_FORMAT_FLOAT32_NE;
-}
-
-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;
-
- case SA_PCM_FORMAT_FLOAT32_NE:
- case SA_PCM_FORMAT_FLOAT32_RE:
- return SA_PCM_FORMAT_FLOAT32_NE;
-
- case _SA_PCM_FORMAT_MAX:
- ;
- }
-
- sa_assert_not_reached();
-}
-
-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;
-
- case SA_PCM_FORMAT_ULAW:
- case SA_PCM_FORMAT_ALAW:
- case SA_PCM_FORMAT_S16_LE:
- case SA_PCM_FORMAT_S16_BE:
- return SA_PCM_FORMAT_S16_NE;
-
- case SA_PCM_FORMAT_S24_LE:
- case SA_PCM_FORMAT_S24_BE:
- 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;
-
- case _SA_PCM_FORMAT_MAX:
- ;
- }
-
- break;
-
- case SA_PCM_FORMAT_S16_LE:
- case SA_PCM_FORMAT_S16_BE:
-
- switch (b) {
- case SA_PCM_FORMAT_U8:
- case SA_PCM_FORMAT_ULAW:
- case SA_PCM_FORMAT_ALAW:
- case SA_PCM_FORMAT_S16_LE:
- case SA_PCM_FORMAT_S16_BE:
- return SA_PCM_FORMAT_S16_NE;
-
- case SA_PCM_FORMAT_S24_LE:
- case SA_PCM_FORMAT_S24_BE:
- 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;
-
- case _SA_PCM_FORMAT_MAX:
- ;
- }
- break;
-
- case SA_PCM_FORMAT_S24_LE:
- case SA_PCM_FORMAT_S24_BE:
- case SA_PCM_FORMAT_S32_LE:
- case SA_PCM_FORMAT_S32_BE:
-
- switch (b) {
- case SA_PCM_FORMAT_U8:
- case SA_PCM_FORMAT_ULAW:
- case SA_PCM_FORMAT_ALAW:
- case SA_PCM_FORMAT_S16_LE:
- case SA_PCM_FORMAT_S16_BE:
- case SA_PCM_FORMAT_S24_LE:
- case SA_PCM_FORMAT_S24_BE:
- 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;
-
- case _SA_PCM_FORMAT_MAX:
- ;
- }
- break;
-
- case SA_PCM_FORMAT_FLOAT32_LE:
- case SA_PCM_FORMAT_FLOAT32_BE:
- return SA_PCM_FORMAT_FLOAT32_NE;
-
- case _SA_PCM_FORMAT_MAX:
- ;
- }
-
- sa_assert_not_reached();
-}
-
-static sa_pcm_format_t fix_work_format_for_resample(sa_pcm_format_t f) {
-
- switch (f) {
- case SA_PCM_FORMAT_U8:
- 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:
- ;
- }
-
- sa_assert_not_reached();
-}
-
-int sa_converter_init(
- sa_converter_t *c,
- const pcm_attrs_t *from,
- const pcm_attrs_t *to,
- int dynamic_rate_enabled) {
-
- unsigned u, t;
- int resample_required;
-
- sa_assert(c);
- sa_assert(from);
- sa_assert(to);
-
- memset(c, 0, sizeof(*c));
-
- c->from_pcm_format = from->format;
- c->to_pcm_format = to->format;
-
- c->from_rate = from->rate;
- c->to_rate = to->rate;
-
- c->from_nchannels = from->nchannels;
- c->to_nchannels = to->nchannels;
-
- if (!(c->channel_map_table = sa_new(int, (from->nchannels+1) * to->nchannels)))
- goto fail;
-
- 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;
-
- resample_required =
- from->rate != to->rate ||
- dynamic_rate_enabled;
-
- 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));
-
- c->from_sample_size = sa_get_pcm_sample_size(c->from_pcm_format);
- c->work_sample_size = sa_get_pcm_sample_size(c->work_pcm_format);
- c->to_sample_size = sa_get_pcm_sample_size(c->to_pcm_format);
-
- /* Get function pointers */
- c->pre_byteswap_func = sa_get_byteswap_func(from->format);
-
- if (byteswap_fix(from->format) != c->work_pcm_format) {
- 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) {
- if (!(c->speex = speex_resampler_init(c->to_nchannels, c->from_rate, c->to_rate, SPEEX_RESAMPLER_QUALITY_DEFAULT, NULL)))
- goto fail;
- }
-
- /* Initialize processing variables */
-
- if (!(c->from_process_data = sa_new0(void*, c->from_nchannels)))
- goto fail;
-
- if (!(c->from_stride = sa_new0(size_t, c->from_nchannels)))
- goto fail;
-
- if (!(c->to_process_data = sa_new0(void*, c->to_nchannels)))
- goto fail;
-
- if (!(c->to_stride = sa_new0(size_t, c->to_nchannels)))
- goto fail;
-
- /* Initialize volume stuff */
- if (!(c->volume_factor = sa_new(int32_t, c->from_nchannels)))
- goto fail;
-
- if (!(c->volume_divisor = sa_new(int32_t, c->from_nchannels)))
- goto fail;
-
- 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)
- goto fail;
- if (sa_bbuffer_init(&c->bb_volscale, c->from_nchannels, c->work_sample_size) < 0)
- goto fail;
- if (sa_bbuffer_init(&c->bb_remap, c->to_nchannels, c->work_sample_size) < 0)
- goto fail;
- if (sa_bbuffer_init(&c->bb_resample, c->to_nchannels, c->work_sample_size) < 0)
- goto fail;
- if (sa_bbuffer_init(&c->bb_post_format, c->to_nchannels, c->to_sample_size) < 0)
- goto fail;
- if (sa_bbuffer_init(&c->bb_post_byteswap, c->to_nchannels, c->to_sample_size) < 0)
- goto fail;
- if (sa_bbuffer_init(&c->bb_interleave, c->to_nchannels, c->to_sample_size) < 0)
- goto fail;
- if (sa_bbuffer_init(&c->bb_tmp, 1, 1) < 0)
- goto fail;
-
- return 0;
-
-fail:
- sa_converter_done(c);
-
- return SA_ERROR_OOM;
-}
-
-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);
- sa_free(c->to_stride);
-
- sa_bbuffer_done(&c->bb_pre_byteswap);
- sa_bbuffer_done(&c->bb_pre_format);
- sa_bbuffer_done(&c->bb_volscale);
- sa_bbuffer_done(&c->bb_remap);
- sa_bbuffer_done(&c->bb_resample);
- sa_bbuffer_done(&c->bb_post_format);
- sa_bbuffer_done(&c->bb_post_byteswap);
- sa_bbuffer_done(&c->bb_interleave);
- sa_bbuffer_done(&c->bb_tmp);
-
- if (c->speex)
- speex_resampler_destroy(c->speex);
-
- sa_free(c->zero_buffer);
-
- sa_free(c->volume_divisor);
- sa_free(c->volume_factor);
- memset(c, 0, sizeof(*c));
-}
-
-void* sa_converter_get_zero_buffer(sa_converter_t *c, size_t size) {
- void *b;
-
- sa_assert(c);
- sa_assert(size > 0);
-
- if (c->zero_buffer && c->zero_size >= size)
- return c->zero_buffer;
-
- sa_free(c->zero_buffer);
-
- if (!(c->zero_buffer = sa_malloc(size)))
- return NULL;
-
- c->zero_func(b, c->work_sample_size, size);
- return c->zero_func;
-}
-
-int sa_converter_go(
- sa_converter_t *c,
- 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;
- stride = (size_t*) sstr;
- process_data = (void**) src;
- interleave = !!sinterleave;
- dinterleave = !!dinterleave;
-
- if (c->no_volume &&
- !c->remap_required &&
- !c->resample_func &&
- c->from_pcm_format == c->to_pcm_format) {
-
- /* We can shortcut this, since we don't need to do any real work.*/
-
- 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;
- }
-
- process_data = c->from_process_data;
- stride = c->from_stride;
- interleave = dinterleave;
- is_bounce = 1;
- }
-
- if (c->pre_format_func) {
-
- if (is_bounce && c->from_sample_size == c->to_sample_size) {
-
- /* 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->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;
- interleave = dinterleave;
- is_bounce = 1;
- }
- }
-
- if (!c->no_volume) {
-
- sa_assert(c->volscale_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->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);
-
- } else {
- size_t k;
-
- 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_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;
- is_bounce = 1;
- }
- }
-
- if (c->remap_required) {
- size_t k;
- int need_proper_interleave = 0;
-
- k = dinterleave ? c->work_sample_size*c->to_nchannels : c->work_sample_size;
-
- 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 */
-
- if (!(b = sa_converter_get_zero_buffer(c, *size)))
- return SA_ERROR_OOM;
-
- c->to_process_data[i] = b;
- c->to_stride[i] = c->work_sample_size;
-
- need_proper_interleave = 1;
- } else if (p[1] == -1) {
- /* Just one channel, nothing to mix */
-
- c->to_process_data[i] = process_data[p[0]];
- c->to_stride[i] = stride[p[0]];
-
- need_proper_interleave = 1;
- } else {
- int j;
-
- /* We have to mix two or more channels */
-
- if (!(b = sa_bbuffer_get(&c->bb_remap, i, *size, dinterleave)))
- return SA_ERROR_OOM;
-
- c->add_func(b, k, process_data[p[0]], stride[p[0]], process_data[p[1]], stride[p[1]], *size);
-
- 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;
- }
- }
-
- process_data = c->to_process_data;
- stride = c->to_stride;
- interleave = need_proper_interleave ? -1 : dinterleave;
- is_bounce = 1;
- }
-
- if (c->resample_func) {
- size_t k;
- size_t new_size;
-
- 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;
-
- if (!(b = sa_bbuffer_get(&c->bb_resample, i, new_size, dinterleave)))
- return SA_ERROR_OOM;
-
- c->resample_func(c->speex, i, b, k, process_data[i], stride[i], *size, &new_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;
- interleave = dinterleave;
- is_bounce = 1;
- }
-
- if (c->post_format_func) {
-
- if (is_bounce && c->work_sample_size == c->to_sample_size) {
-
- /* 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);
-
- } else {
- size_t k, new_size;
-
- 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;
- interleave = dinterleave;
- 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);
-
- } else {
- 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;
- }
-
- process_data = c->to_process_data;
- stride = c->to_stride;
- interleave = dinterleave;
- is_bounce = 1;
- }
- }
-
-do_interleave:
-
- if (interleave != dinterleave) {
- 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_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;
- is_bounce = 1;
- }
-
- *dstr = stride;
- *dst = process_data;
-
- return SA_SUCCESS;
-}
-
-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++) {
- int num, denom;
-
- if (vol[i] == 0) {
- c->volume_factor[i] = 1;
- c->volume_divisor[i] = 1;
- } else if (vol[i] <= SA_VOLUME_MUTED) {
- c->volume_factor[i] = 0;
- c->volume_divisor[i] = 1;
- 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;
- }
- }
-
- c->no_volume = no_volume;
-}
-
-int sa_converter_go_interleaved(
- sa_converter_t *c,
- const void *const data,
- void **dst[], size_t *dstr[], int dinterleave,
- size_t *size) {
-
- unsigned i;
- const uint8_t *d = data;
- unsigned stride = c->from_nchannels * c->from_sample_size;
-
- for (i = 0; i < c->from_nchannels; i++) {
- c->from_process_data[i] = (void*) data;
- d += c->from_sample_size;
- c->from_stride[i] = stride;
- }
-
- return sa_converter_go(c, (const void *const*) c->from_process_data, c->from_stride, 1, dst, dstr, dinterleave, size);
-}
-
-void sa_converter_set_ratio(sa_converter_t *c, unsigned rate1, unsigned rate2) {
- assert(c);
- assert(c->speex);
-
- speex_resampler_set_rate(c->speex, rate1, rate2);
-}