From a64e85acf96bc0c55363fe55c9e9116aef2a8584 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 May 2007 23:38:38 +0000 Subject: resampling works git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@4 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce --- resample.c | 172 +++++++++---------------------------------------------------- 1 file changed, 25 insertions(+), 147 deletions(-) (limited to 'resample.c') diff --git a/resample.c b/resample.c index f69e6d6..292f891 100644 --- a/resample.c +++ b/resample.c @@ -1,164 +1,42 @@ -#include "sydney.h" +#include "macro.h" +#include "resample.h" -#define MAX_OPERATIONS 10 +static void resample_s16(SpeexResamplerState *speex, unsigned channel, void *dst, size_t dstr, const void *src, size_t sstr, size_t in_bytes, size_t *out_bytes) { -typedef struct buffer_spec buffer_spec_t; - -struct buffer_spec { - void *data; - size_t size; - size_t max_size; -}; - -typedef struct operation operation_t; - -typedef void (*operation_execute_t)(operation_t *o, buffer_spec_t *source); - -struct operation { - operation_execute_t execute; - - struct buffer_spec result; - - size_t sample - unsigned nchannels; -}; - -typedef struct pipeline pipeline_t; - -struct pipeline { - operation_t operations[MAX_OPERATIONS]; -}; - -static int native_pcm_format(pcm_format_t f) { - - /* Sample formats we know to handle natively */ - - return - f == SA_PCM_FORMAT_S16_NE || - f == SA_PCM_FORMAT_S32_NE || - f == SA_PCM_FORMAT_FLOAT32_NE; + spx_uint32_t in_samples = in_bytes/sizeof(int16_t), out_samples = *out_bytes/sizeof(int16_t); -} - -/* Steps: prefmt -> volume -> remap -> resample -> postfmt */ + speex_resampler_set_input_stride(speex, sstr/sizeof(int16_t)); + speex_resampler_set_input_stride(speex, dstr/sizeof(int16_t)); -int build_pipeline_output( - sa_device_t *dev, - sa_pipeline_t *pipeline, - sa_pcm_format format, - unsigned rate, - unsigned nchannels, - const sa_channel_t map[]) { + speex_resampler_process_int(speex, channel, src, &in_samples, dst, &out_samples); - int *channel_map_table; - unsigned u, t; - int prefmt_required; - int sum_required = 0; - int o = 0; - pcm_format_t work_format; - operation_execute_t func; - - sa_assert(dev); - sa_assert(pipeline); + sa_assert(in_samples == in_bytes/sizeof(int16_t)); - if (!(channel_map_table = sa_new(int, nchannels * dev->nchannels))) - return SA_ERROR_OOM; - - for (u = 0; u < nchannels; u++) { - unsigned k = 0; - - for (t = 0; t < dev->nchannels; t++) { + *out_bytes = out_samples * sizeof(int16_t); +} - if (map[u] == map[t]) - channel_map_table[u * dev->nchannels + k++] += t; - } +static void resample_f32(SpeexResamplerState *speex, unsigned channel, void *dst, size_t dstr, const void *src, size_t sstr, size_t in_bytes, size_t *out_bytes) { - if (k > 1) - sum_required = 1; - - channel_map_table[k] = (unsigned) -1; - } + spx_uint32_t in_samples = in_bytes/sizeof(float), out_samples = *out_bytes/sizeof(float); - prefmt_required = - sum_required || - dev->output_volume != 0 || - dev->rate != rate || - dev->dsr_enabled; - - if (native_pcm_format(dev->pcm_format)) - prefmt_required = 0; - - if (prefmt_required) { - - switch (dev->pcm_format) { - 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: - work_format = SA_PCM_FORMAT_S16_NE; - break; + speex_resampler_set_input_stride(speex, sstr/sizeof(float)); + speex_resampler_set_input_stride(speex, dstr/sizeof(float)); - case SA_PCM_FORMAT_S24_LE: - case SA_PCM_FORMAT_S24_BE: - case SA_PCM_FORMAT_S32_LE: - case SA_PCM_FORMAT_S32_BE: - work_format = SA_PCM_FORMAT_S32_NE; - break; + speex_resampler_process_float(speex, channel, src, &in_samples, dst, &out_samples); - case SA_PCM_FORMAT_FLOAT32_LE: - case SA_PCM_FORMAT_FLOAT32_BE: - work_format = SA_PCM_FORMAT_FLOAT32_NE; - break; - } - - sa_assert(native_pcm_format(work_format)); + sa_assert(in_samples == in_bytes/sizeof(float)); - func = get_format_converter(dev->pcm_format, work_format); - pipeline.operations[o].execute = func; - pipeline.operations[o].buffer.data = NULL; - pipeline.operations[o].buffer.stride = dev->nchannels * get_sample_size(dev->work_format); - pipeline.operations[o]. - o++; - - } else - work_format = dev->pcm_format; - - if (dev->output_volume != 0) { - pipeline.operations[o].execute = get_scaler(work_format); - pipeline.operations[o].buffer.data = NULL; - o++; - } - - if (dev->rate != rate || dev->dsr_enabled) { - pipeline.operations[o].execute = get_resampler(work_format); - pipeline.operations[o].buffer.data = NULL; - o++; - } - - if (work_format != pcm_format) { - pipeline.operations[o].execute = get_format_converter(work_format, pcm_format); - pipeline.operations[o].buffer.data = NULL; - o++; - } - - pipeline.operations[o].execute = NULL; - - - + *out_bytes = out_samples * sizeof(float); } -void execute_pipeline(sa_device_t *dev, pipeline_t *pipeline, const buffer_spec_t *buffer, buffer_spec_t *output) { - sa_operation_t *o; - - sa_assert(dev); - sa_assert(pipeline); - sa_assert(buffer); +resample_func_t get_resample_func(sa_pcm_format_t f) { + + static const resample_func_t funcs[SA_PCM_FORMAT_MAX] = { + [SA_PCM_FORMAT_S16_NE] = resample_s16, + [SA_PCM_FORMAT_FLOAT32_NE] = resample_f32 + }; - for (o = pipeline->operations; o->execute; o++) { - o->execute(o, buffer); - buffer = &o->buffer; - } + sa_assert(f < SA_PCM_FORMAT_MAX); - *output = *buffer; + return funcs[f]; } -- cgit