summaryrefslogtreecommitdiffstats
path: root/resample.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-04-25 10:27:13 +0000
committerLennart Poettering <lennart@poettering.net>2007-04-25 10:27:13 +0000
commit2eb6dec8e9f0114bdbad59cf8f11f197f8fdaaf3 (patch)
tree88a2b13b2fc9abdd9fa43136d4ed91bdc084d929 /resample.c
parent130f9f7046eec89f7674cad7f66c831fa8d0127d (diff)
initial commit
git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@3 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce
Diffstat (limited to 'resample.c')
-rw-r--r--resample.c164
1 files changed, 164 insertions, 0 deletions
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;
+}