annotate ffmpeg/libswresample/dither.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Copyright (C) 2012-2013 Michael Niedermayer (michaelni@gmx.at)
yading@11 3 *
yading@11 4 * This file is part of libswresample
yading@11 5 *
yading@11 6 * libswresample is free software; you can redistribute it and/or
yading@11 7 * modify it under the terms of the GNU Lesser General Public
yading@11 8 * License as published by the Free Software Foundation; either
yading@11 9 * version 2.1 of the License, or (at your option) any later version.
yading@11 10 *
yading@11 11 * libswresample is distributed in the hope that it will be useful,
yading@11 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 14 * Lesser General Public License for more details.
yading@11 15 *
yading@11 16 * You should have received a copy of the GNU Lesser General Public
yading@11 17 * License along with libswresample; if not, write to the Free Software
yading@11 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 19 */
yading@11 20
yading@11 21 #include "libavutil/avassert.h"
yading@11 22 #include "swresample_internal.h"
yading@11 23
yading@11 24 #include "noise_shaping_data.c"
yading@11 25
yading@11 26 void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSampleFormat noise_fmt) {
yading@11 27 double scale = s->dither.noise_scale;
yading@11 28 #define TMP_EXTRA 2
yading@11 29 double *tmp = av_malloc((len + TMP_EXTRA) * sizeof(double));
yading@11 30 int i;
yading@11 31
yading@11 32 for(i=0; i<len + TMP_EXTRA; i++){
yading@11 33 double v;
yading@11 34 seed = seed* 1664525 + 1013904223;
yading@11 35
yading@11 36 switch(s->dither.method){
yading@11 37 case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break;
yading@11 38 default:
yading@11 39 av_assert0(s->dither.method < SWR_DITHER_NB);
yading@11 40 v = ((double)seed) / UINT_MAX;
yading@11 41 seed = seed*1664525 + 1013904223;
yading@11 42 v-= ((double)seed) / UINT_MAX;
yading@11 43 break;
yading@11 44 }
yading@11 45 tmp[i] = v;
yading@11 46 }
yading@11 47
yading@11 48 for(i=0; i<len; i++){
yading@11 49 double v;
yading@11 50
yading@11 51 switch(s->dither.method){
yading@11 52 default:
yading@11 53 av_assert0(s->dither.method < SWR_DITHER_NB);
yading@11 54 v = tmp[i];
yading@11 55 break;
yading@11 56 case SWR_DITHER_TRIANGULAR_HIGHPASS :
yading@11 57 v = (- tmp[i] + 2*tmp[i+1] - tmp[i+2]) / sqrt(6);
yading@11 58 break;
yading@11 59 }
yading@11 60
yading@11 61 v*= scale;
yading@11 62
yading@11 63 switch(noise_fmt){
yading@11 64 case AV_SAMPLE_FMT_S16P: ((int16_t*)dst)[i] = v; break;
yading@11 65 case AV_SAMPLE_FMT_S32P: ((int32_t*)dst)[i] = v; break;
yading@11 66 case AV_SAMPLE_FMT_FLTP: ((float *)dst)[i] = v; break;
yading@11 67 case AV_SAMPLE_FMT_DBLP: ((double *)dst)[i] = v; break;
yading@11 68 default: av_assert0(0);
yading@11 69 }
yading@11 70 }
yading@11 71
yading@11 72 av_free(tmp);
yading@11 73 }
yading@11 74
yading@11 75 int swri_dither_init(SwrContext *s, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt)
yading@11 76 {
yading@11 77 int i;
yading@11 78 double scale = 0;
yading@11 79
yading@11 80 if (s->dither.method > SWR_DITHER_TRIANGULAR_HIGHPASS && s->dither.method <= SWR_DITHER_NS)
yading@11 81 return AVERROR(EINVAL);
yading@11 82
yading@11 83 out_fmt = av_get_packed_sample_fmt(out_fmt);
yading@11 84 in_fmt = av_get_packed_sample_fmt( in_fmt);
yading@11 85
yading@11 86 if(in_fmt == AV_SAMPLE_FMT_FLT || in_fmt == AV_SAMPLE_FMT_DBL){
yading@11 87 if(out_fmt == AV_SAMPLE_FMT_S32) scale = 1.0/(1L<<31);
yading@11 88 if(out_fmt == AV_SAMPLE_FMT_S16) scale = 1.0/(1L<<15);
yading@11 89 if(out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1.0/(1L<< 7);
yading@11 90 }
yading@11 91 if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_S16) scale = 1L<<16;
yading@11 92 if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<24;
yading@11 93 if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<8;
yading@11 94
yading@11 95 scale *= s->dither.scale;
yading@11 96
yading@11 97 if (out_fmt == AV_SAMPLE_FMT_S32 && s->dither.output_sample_bits)
yading@11 98 scale *= 1<<(32-s->dither.output_sample_bits);
yading@11 99
yading@11 100 s->dither.ns_pos = 0;
yading@11 101 s->dither.noise_scale= scale;
yading@11 102 s->dither.ns_scale = scale;
yading@11 103 s->dither.ns_scale_1 = scale ? 1/scale : 0;
yading@11 104 memset(s->dither.ns_errors, 0, sizeof(s->dither.ns_errors));
yading@11 105 for (i=0; filters[i].coefs; i++) {
yading@11 106 const filter_t *f = &filters[i];
yading@11 107 if (fabs(s->out_sample_rate - f->rate) / f->rate <= .05 && f->name == s->dither.method) {
yading@11 108 int j;
yading@11 109 s->dither.ns_taps = f->len;
yading@11 110 for (j=0; j<f->len; j++)
yading@11 111 s->dither.ns_coeffs[j] = f->coefs[j];
yading@11 112 s->dither.ns_scale_1 *= 1 - exp(f->gain_cB * M_LN10 * 0.005) * 2 / (1<<(8*av_get_bytes_per_sample(out_fmt)));
yading@11 113 break;
yading@11 114 }
yading@11 115 }
yading@11 116 if (!filters[i].coefs && s->dither.method > SWR_DITHER_NS) {
yading@11 117 av_log(s, AV_LOG_WARNING, "Requested noise shaping dither not available at this sampling rate, using triangular hp dither\n");
yading@11 118 s->dither.method = SWR_DITHER_TRIANGULAR_HIGHPASS;
yading@11 119 }
yading@11 120
yading@11 121 av_assert0(!s->preout.count);
yading@11 122 s->dither.noise = s->preout;
yading@11 123 s->dither.temp = s->preout;
yading@11 124 if (s->dither.method > SWR_DITHER_NS) {
yading@11 125 s->dither.noise.bps = 4;
yading@11 126 s->dither.noise.fmt = AV_SAMPLE_FMT_FLTP;
yading@11 127 s->dither.noise_scale = 1;
yading@11 128 }
yading@11 129
yading@11 130 return 0;
yading@11 131 }
yading@11 132
yading@11 133 #define TEMPLATE_DITHER_S16
yading@11 134 #include "dither_template.c"
yading@11 135 #undef TEMPLATE_DITHER_S16
yading@11 136
yading@11 137 #define TEMPLATE_DITHER_S32
yading@11 138 #include "dither_template.c"
yading@11 139 #undef TEMPLATE_DITHER_S32
yading@11 140
yading@11 141 #define TEMPLATE_DITHER_FLT
yading@11 142 #include "dither_template.c"
yading@11 143 #undef TEMPLATE_DITHER_FLT
yading@11 144
yading@11 145 #define TEMPLATE_DITHER_DBL
yading@11 146 #include "dither_template.c"
yading@11 147 #undef TEMPLATE_DITHER_DBL