diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-01-09 18:03:49 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-01-09 18:25:06 +0100 |
commit | 82742294b7a866b89d6fd228b0692867d9e08fcd (patch) | |
tree | 054242b79f9f2ad1dfa6b85d5bbfe3e24d83d3ed /libswresample/dither.c | |
parent | 5b69c07d12b1e505fd7468828ed85d6d8d634621 (diff) | |
download | ffmpeg-82742294b7a866b89d6fd228b0692867d9e08fcd.tar.gz |
swr: Implement Noise shaping dither
The following variants are implemented:
lipshitz noise shaping dither
shibata noise shaping dither
low shibata noise shaping dither
high shibata noise shaping dither
f-weighted noise shaping dither
modified-e-weighted noise shaping dither
improved-e-weighted noise shaping dither
Data tables taken from SOX
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libswresample/dither.c')
-rw-r--r-- | libswresample/dither.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/libswresample/dither.c b/libswresample/dither.c index 79113f4c23..bc6c02de75 100644 --- a/libswresample/dither.c +++ b/libswresample/dither.c @@ -21,6 +21,8 @@ #include "libavutil/avassert.h" #include "swresample_internal.h" +#include "noise_shaping_data.c" + void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt) { double scale = 0; #define TMP_EXTRA 2 @@ -41,19 +43,37 @@ void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSa scale *= s->dither_scale; + s->ns_pos = 0; + s->ns_scale = scale; + s->ns_scale_1 = 1/scale; + memset(s->ns_errors, 0, sizeof(s->ns_errors)); + for (i=0; filters[i].coefs; i++) { + const filter_t *f = &filters[i]; + if (fabs(s->out_sample_rate - f->rate) / f->rate <= .05 && f->name == s->dither_method) { + int j; + s->ns_taps = f->len; + for (j=0; j<f->len; j++) + s->ns_coeffs[j] = f->coefs[j]; + break; + } + } + if (!filters[i].coefs && s->dither_method > SWR_DITHER_NS) { + av_log(s, AV_LOG_WARNING, "Requested noise shaping dither not available at this sampling rate, using triangular hp dither\n"); + s->dither_method = SWR_DITHER_TRIANGULAR_HIGHPASS; + } + for(i=0; i<len + TMP_EXTRA; i++){ double v; seed = seed* 1664525 + 1013904223; switch(s->dither_method){ case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break; - case SWR_DITHER_TRIANGULAR : - case SWR_DITHER_TRIANGULAR_HIGHPASS : + default: + av_assert0(s->dither_method < SWR_DITHER_NB); v = ((double)seed) / UINT_MAX; seed = seed*1664525 + 1013904223; v-= ((double)seed) / UINT_MAX; break; - default: av_assert0(0); } tmp[i] = v; } @@ -62,14 +82,13 @@ void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSa double v; switch(s->dither_method){ - case SWR_DITHER_RECTANGULAR: - case SWR_DITHER_TRIANGULAR : + default: + av_assert0(s->dither_method < SWR_DITHER_NB); v = tmp[i]; break; case SWR_DITHER_TRIANGULAR_HIGHPASS : v = (- tmp[i] + 2*tmp[i+1] - tmp[i+2]) / sqrt(6); break; - default: av_assert0(0); } v*= scale; @@ -85,3 +104,19 @@ void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSa av_free(tmp); } + +#define TEMPLATE_DITHER_S16 +#include "dither_template.c" +#undef TEMPLATE_DITHER_S16 + +#define TEMPLATE_DITHER_S32 +#include "dither_template.c" +#undef TEMPLATE_DITHER_S32 + +#define TEMPLATE_DITHER_FLT +#include "dither_template.c" +#undef TEMPLATE_DITHER_FLT + +#define TEMPLATE_DITHER_DBL +#include "dither_template.c" +#undef TEMPLATE_DITHER_DBL |