summaryrefslogtreecommitdiff
path: root/libswresample/resample_template.c
diff options
context:
space:
mode:
Diffstat (limited to 'libswresample/resample_template.c')
-rw-r--r--libswresample/resample_template.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/libswresample/resample_template.c b/libswresample/resample_template.c
new file mode 100644
index 0000000000..7e80ef995a
--- /dev/null
+++ b/libswresample/resample_template.c
@@ -0,0 +1,187 @@
+/*
+ * audio resampling
+ * Copyright (c) 2004-2012 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * audio resampling
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#if defined(TEMPLATE_RESAMPLE_DBL)
+
+# define RENAME(N) N ## _double
+# define FILTER_SHIFT 0
+# define DELEM double
+# define FELEM double
+# define FELEM2 double
+# define OUT(d, v) d = v
+
+#elif defined(TEMPLATE_RESAMPLE_FLT)
+
+# define RENAME(N) N ## _float
+# define FILTER_SHIFT 0
+# define DELEM float
+# define FELEM float
+# define FELEM2 float
+# define OUT(d, v) d = v
+
+#elif defined(TEMPLATE_RESAMPLE_S32)
+
+# define RENAME(N) N ## _int32
+# define FILTER_SHIFT 30
+# define DELEM int32_t
+# define FELEM int32_t
+# define FELEM2 int64_t
+# define FELEM_MAX INT32_MAX
+# define FELEM_MIN INT32_MIN
+# define OUT(d, v) (v) = ((v) + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\
+ (d) = (uint64_t)((v) + 0x80000000) > 0xFFFFFFFF ? ((v)>>63) ^ 0x7FFFFFFF : (v)
+
+#elif defined(TEMPLATE_RESAMPLE_S16)
+
+# define RENAME(N) N ## _int16
+# define FILTER_SHIFT 15
+# define DELEM int16_t
+# define FELEM int16_t
+# define FELEM2 int32_t
+# define FELEML int64_t
+# define FELEM_MAX INT16_MAX
+# define FELEM_MIN INT16_MIN
+# define OUT(d, v) (v) = ((v) + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\
+ (d) = (unsigned)((v) + 32768) > 65535 ? ((v)>>31) ^ 32767 : (v)
+
+#endif
+
+static void RENAME(resample_one)(void *dest, const void *source,
+ int dst_size, int64_t index2, int64_t incr)
+{
+ DELEM *dst = dest;
+ const DELEM *src = source;
+ int dst_index;
+
+ for (dst_index = 0; dst_index < dst_size; dst_index++) {
+ dst[dst_index] = src[index2 >> 32];
+ index2 += incr;
+ }
+}
+
+static int RENAME(resample_common)(ResampleContext *c,
+ void *dest, const void *source,
+ int n, int update_ctx)
+{
+ DELEM *dst = dest;
+ const DELEM *src = source;
+ int dst_index;
+ int index= c->index;
+ int frac= c->frac;
+ int sample_index = index >> c->phase_shift;
+
+ index &= c->phase_mask;
+ for (dst_index = 0; dst_index < n; dst_index++) {
+ FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
+
+ FELEM2 val=0;
+ int i;
+ for (i = 0; i < c->filter_length; i++) {
+ val += src[sample_index + i] * (FELEM2)filter[i];
+ }
+ OUT(dst[dst_index], val);
+
+ frac += c->dst_incr_mod;
+ index += c->dst_incr_div;
+ if (frac >= c->src_incr) {
+ frac -= c->src_incr;
+ index++;
+ }
+ sample_index += index >> c->phase_shift;
+ index &= c->phase_mask;
+ }
+
+ if(update_ctx){
+ c->frac= frac;
+ c->index= index;
+ }
+
+ return sample_index;
+}
+
+static int RENAME(resample_linear)(ResampleContext *c,
+ void *dest, const void *source,
+ int n, int update_ctx)
+{
+ DELEM *dst = dest;
+ const DELEM *src = source;
+ int dst_index;
+ int index= c->index;
+ int frac= c->frac;
+ int sample_index = index >> c->phase_shift;
+#if FILTER_SHIFT == 0
+ double inv_src_incr = 1.0 / c->src_incr;
+#endif
+
+ index &= c->phase_mask;
+ for (dst_index = 0; dst_index < n; dst_index++) {
+ FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
+ FELEM2 val=0, v2 = 0;
+
+ int i;
+ for (i = 0; i < c->filter_length; i++) {
+ val += src[sample_index + i] * (FELEM2)filter[i];
+ v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc];
+ }
+#ifdef FELEML
+ val += (v2 - val) * (FELEML) frac / c->src_incr;
+#else
+# if FILTER_SHIFT == 0
+ val += (v2 - val) * inv_src_incr * frac;
+# else
+ val += (v2 - val) / c->src_incr * frac;
+# endif
+#endif
+ OUT(dst[dst_index], val);
+
+ frac += c->dst_incr_mod;
+ index += c->dst_incr_div;
+ if (frac >= c->src_incr) {
+ frac -= c->src_incr;
+ index++;
+ }
+ sample_index += index >> c->phase_shift;
+ index &= c->phase_mask;
+ }
+
+ if(update_ctx){
+ c->frac= frac;
+ c->index= index;
+ }
+
+ return sample_index;
+}
+
+#undef RENAME
+#undef FILTER_SHIFT
+#undef DELEM
+#undef FELEM
+#undef FELEM2
+#undef FELEML
+#undef FELEM_MAX
+#undef FELEM_MIN
+#undef OUT