diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2012-10-31 23:40:12 +0400 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-12-20 03:52:54 +0400 |
commit | b2fe6756e34d1316d0fa799e8a5ace993059c407 (patch) | |
tree | 0fc8dea25140a8af90cdfb96af5b5d8f97560ab7 /libavresample/audio_convert.c | |
parent | 582368626188c070d4300913c6da5efa4c24cfb2 (diff) |
lavr: add option for dithering during sample format conversion to s16
Diffstat (limited to 'libavresample/audio_convert.c')
-rw-r--r-- | libavresample/audio_convert.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/libavresample/audio_convert.c b/libavresample/audio_convert.c index dcf8a39b06..eb3bc1f1de 100644 --- a/libavresample/audio_convert.c +++ b/libavresample/audio_convert.c @@ -29,6 +29,8 @@ #include "libavutil/samplefmt.h" #include "audio_convert.h" #include "audio_data.h" +#include "dither.h" +#include "internal.h" enum ConvFuncType { CONV_FUNC_TYPE_FLAT, @@ -46,6 +48,7 @@ typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len, struct AudioConvert { AVAudioResampleContext *avr; + DitherContext *dc; enum AVSampleFormat in_fmt; enum AVSampleFormat out_fmt; int channels; @@ -246,10 +249,18 @@ static void set_generic_function(AudioConvert *ac) SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL) } +void ff_audio_convert_free(AudioConvert **ac) +{ + if (!*ac) + return; + ff_dither_free(&(*ac)->dc); + av_freep(ac); +} + AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, - int channels) + int channels, int sample_rate) { AudioConvert *ac; int in_planar, out_planar; @@ -263,6 +274,17 @@ AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, ac->in_fmt = in_fmt; ac->channels = channels; + if (avr->dither_method != AV_RESAMPLE_DITHER_NONE && + av_get_packed_sample_fmt(out_fmt) == AV_SAMPLE_FMT_S16 && + av_get_bytes_per_sample(in_fmt) > 2) { + ac->dc = ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate); + if (!ac->dc) { + av_free(ac); + return NULL; + } + return ac; + } + in_planar = av_sample_fmt_is_planar(in_fmt); out_planar = av_sample_fmt_is_planar(out_fmt); @@ -289,6 +311,15 @@ int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) int use_generic = 1; int len = in->nb_samples; + if (ac->dc) { + /* dithered conversion */ + av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (dithered)\n", + len, av_get_sample_fmt_name(ac->in_fmt), + av_get_sample_fmt_name(ac->out_fmt)); + + return ff_convert_dither(ac->dc, out, in); + } + /* determine whether to use the optimized function based on pointer and samples alignment in both the input and output */ if (ac->has_optimized_func) { |