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/swresample.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/swresample.c')
-rw-r--r-- | libswresample/swresample.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 09ed7b1dff..43609f17cf 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -78,7 +78,14 @@ static const AVOption options[]={ {"dither_method" , "set dither method" , OFFSET(dither_method ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_DITHER_NB-1, PARAM, "dither_method"}, {"rectangular" , "select rectangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_RECTANGULAR}, INT_MIN, INT_MAX , PARAM, "dither_method"}, {"triangular" , "select triangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR }, INT_MIN, INT_MAX , PARAM, "dither_method"}, -{"triangular_hp" , "select triangular dither with high pass" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"triangular_hp" , "select triangular dither with high pass" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"lipshitz" , "select lipshitz noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_LIPSHITZ}, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"shibata" , "select shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"low_shibata" , "select low shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_LOW_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"high_shibata" , "select high shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_HIGH_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"f_weighted" , "select f-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_F_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"modified_e_weighted" , "select modified-e-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_MODIFIED_E_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"improved_e_weighted" , "select improved-e-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_IMPROVED_E_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, {"filter_size" , "set swr resampling filter size", OFFSET(filter_size) , AV_OPT_TYPE_INT , {.i64=32 }, 0 , INT_MAX , PARAM }, {"phase_shift" , "set swr resampling phase shift", OFFSET(phase_shift) , AV_OPT_TYPE_INT , {.i64=10 }, 0 , 30 , PARAM }, @@ -637,7 +644,7 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(preout != out && out_count){ if(s->dither_method){ - int ch; + int ch, len1; int dither_count= FFMAX(out_count, 1<<16); av_assert0(preout != in); @@ -651,19 +658,28 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(s->dither_pos + out_count > s->dither.count) s->dither_pos = 0; - if (s->mix_2_1_simd) { - int len1= out_count&~15; - int off = len1 * preout->bps; - - if(len1) - for(ch=0; ch<preout->ch_count; ch++) - s->mix_2_1_simd(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, len1); - if(out_count != len1) + if (s->dither_method < SWR_DITHER_NS){ + if (s->mix_2_1_simd) { + int len1= out_count&~15; + int off = len1 * preout->bps; + + if(len1) + for(ch=0; ch<preout->ch_count; ch++) + s->mix_2_1_simd(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, len1); + if(out_count != len1) + for(ch=0; ch<preout->ch_count; ch++) + s->mix_2_1_f(preout->ch[ch] + off, preout->ch[ch] + off, s->dither.ch[ch] + s->dither.bps * s->dither_pos + off + len1, s->native_one, 0, 0, out_count - len1); + } else { for(ch=0; ch<preout->ch_count; ch++) - s->mix_2_1_f(preout->ch[ch] + off, preout->ch[ch] + off, s->dither.ch[ch] + s->dither.bps * s->dither_pos + off + len1, s->native_one, 0, 0, out_count - len1); + s->mix_2_1_f(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, out_count); + } } else { - for(ch=0; ch<preout->ch_count; ch++) - s->mix_2_1_f(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, out_count); + switch(s->int_sample_fmt) { + case AV_SAMPLE_FMT_S16P :swri_noise_shaping_int16(s, preout, &s->dither, out_count); break; + case AV_SAMPLE_FMT_S32P :swri_noise_shaping_int32(s, preout, &s->dither, out_count); break; + case AV_SAMPLE_FMT_FLTP :swri_noise_shaping_float(s, preout, &s->dither, out_count); break; + case AV_SAMPLE_FMT_DBLP :swri_noise_shaping_double(s,preout, &s->dither, out_count); break; + } } s->dither_pos += out_count; } |