From 2eb6dec8e9f0114bdbad59cf8f11f197f8fdaaf3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 25 Apr 2007 10:27:13 +0000 Subject: initial commit git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@3 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce --- resample.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 resample.c (limited to 'resample.c') diff --git a/resample.c b/resample.c new file mode 100644 index 0000000..f69e6d6 --- /dev/null +++ b/resample.c @@ -0,0 +1,164 @@ +#include "sydney.h" + +#define MAX_OPERATIONS 10 + +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; + +} + +/* Steps: prefmt -> volume -> remap -> resample -> postfmt */ + +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[]) { + + 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); + + 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++) { + + if (map[u] == map[t]) + channel_map_table[u * dev->nchannels + k++] += t; + } + + if (k > 1) + sum_required = 1; + + channel_map_table[k] = (unsigned) -1; + } + + 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; + + 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; + + 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)); + + 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; + + + +} + +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); + + for (o = pipeline->operations; o->execute; o++) { + o->execute(o, buffer); + buffer = &o->buffer; + } + + *output = *buffer; +} -- cgit