diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-04-11 13:27:22 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-04-11 13:27:22 +0200 |
commit | f8a237a3074b444a8d88d92d9fcce10508479d35 (patch) | |
tree | 06f53bfb00674b57b04bec3fefa4832e45c77111 | |
parent | 1fc4ff2205cdad4fbb7225f0f32cb7e32edc1eec (diff) | |
download | ffmpeg-f8a237a3074b444a8d88d92d9fcce10508479d35.tar.gz |
swr: add triangular highpass dither
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libswresample/dither.c | 23 | ||||
-rw-r--r-- | libswresample/swresample.c | 1 | ||||
-rw-r--r-- | libswresample/swresample.h | 1 |
3 files changed, 24 insertions, 1 deletions
diff --git a/libswresample/dither.c b/libswresample/dither.c index 663e2007ba..88f788066e 100644 --- a/libswresample/dither.c +++ b/libswresample/dither.c @@ -23,6 +23,8 @@ void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, enum SwrDitherType method) { double scale = 0; +#define TMP_EXTRA 2 + double *tmp = av_malloc((len + TMP_EXTRA) * sizeof(double)); int i; if(in_fmt == AV_SAMPLE_FMT_FLT || in_fmt == AV_SAMPLE_FMT_DBL){ @@ -34,19 +36,36 @@ void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_ if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<24; if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<8; - for(i=0; i<len; i++){ + for(i=0; i<len + TMP_EXTRA; i++){ double v; seed = seed* 1664525 + 1013904223; switch(method){ case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break; case SWR_DITHER_TRIANGULAR : + case SWR_DITHER_TRIANGULAR_HIGHPASS : v = ((double)seed) / UINT_MAX; seed = seed*1664525 + 1013904223; v-= ((double)seed) / UINT_MAX; break; default: av_assert0(0); } + tmp[i] = v; + } + + for(i=0; i<len; i++){ + double v; + + switch(method){ + case SWR_DITHER_RECTANGULAR: + case SWR_DITHER_TRIANGULAR : + 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; @@ -58,4 +77,6 @@ void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_ default: av_assert0(0); } } + + av_free(tmp); } diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 715a446456..78b0355c4f 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -56,6 +56,7 @@ static const AVOption options[]={ {"dither", "dither method" , OFFSET(dither_method), AV_OPT_TYPE_INT, {.dbl=0}, 0, SWR_DITHER_NB-1, 0, "dither_method"}, {"rectangular", "rectangular dither", 0, AV_OPT_TYPE_CONST, {.dbl=SWR_DITHER_RECTANGULAR}, INT_MIN, INT_MAX, 0, "dither_method"}, {"triangular" , "triangular dither" , 0, AV_OPT_TYPE_CONST, {.dbl=SWR_DITHER_TRIANGULAR }, INT_MIN, INT_MAX, 0, "dither_method"}, +{"triangular_hp" , "triangular dither with high pass" , 0, AV_OPT_TYPE_CONST, {.dbl=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, 0, "dither_method"}, {0} }; diff --git a/libswresample/swresample.h b/libswresample/swresample.h index 3a54c8eed9..137517d6d2 100644 --- a/libswresample/swresample.h +++ b/libswresample/swresample.h @@ -49,6 +49,7 @@ enum SwrDitherType { SWR_DITHER_NONE = 0, SWR_DITHER_RECTANGULAR, SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, SWR_DITHER_NB, ///< not part of API/ABI }; |