LCOV - code coverage report
Current view: top level - src/libavresample - dither.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 193 0.0 %
Date: 2017-03-25 17:02:41 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
       3             :  *
       4             :  * Triangular with Noise Shaping is based on opusfile.
       5             :  * Copyright (c) 1994-2012 by the Xiph.Org Foundation and contributors
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : /**
      25             :  * @file
      26             :  * Dithered Audio Sample Quantization
      27             :  *
      28             :  * Converts from dbl, flt, or s32 to s16 using dithering.
      29             :  */
      30             : 
      31             : #include <math.h>
      32             : #include <stdint.h>
      33             : 
      34             : #include "libavutil/attributes.h"
      35             : #include "libavutil/common.h"
      36             : #include "libavutil/lfg.h"
      37             : #include "libavutil/mem.h"
      38             : #include "libavutil/samplefmt.h"
      39             : #include "audio_convert.h"
      40             : #include "dither.h"
      41             : #include "internal.h"
      42             : 
      43             : typedef struct DitherState {
      44             :     int mute;
      45             :     unsigned int seed;
      46             :     AVLFG lfg;
      47             :     float *noise_buf;
      48             :     int noise_buf_size;
      49             :     int noise_buf_ptr;
      50             :     float dither_a[4];
      51             :     float dither_b[4];
      52             : } DitherState;
      53             : 
      54             : struct DitherContext {
      55             :     DitherDSPContext  ddsp;
      56             :     enum AVResampleDitherMethod method;
      57             :     int apply_map;
      58             :     ChannelMapInfo *ch_map_info;
      59             : 
      60             :     int mute_dither_threshold;  // threshold for disabling dither
      61             :     int mute_reset_threshold;   // threshold for resetting noise shaping
      62             :     const float *ns_coef_b;     // noise shaping coeffs
      63             :     const float *ns_coef_a;     // noise shaping coeffs
      64             : 
      65             :     int channels;
      66             :     DitherState *state;         // dither states for each channel
      67             : 
      68             :     AudioData *flt_data;        // input data in fltp
      69             :     AudioData *s16_data;        // dithered output in s16p
      70             :     AudioConvert *ac_in;        // converter for input to fltp
      71             :     AudioConvert *ac_out;       // converter for s16p to s16 (if needed)
      72             : 
      73             :     void (*quantize)(int16_t *dst, const float *src, float *dither, int len);
      74             :     int samples_align;
      75             : };
      76             : 
      77             : /* mute threshold, in seconds */
      78             : #define MUTE_THRESHOLD_SEC 0.000333
      79             : 
      80             : /* scale factor for 16-bit output.
      81             :    The signal is attenuated slightly to avoid clipping */
      82             : #define S16_SCALE 32753.0f
      83             : 
      84             : /* scale to convert lfg from INT_MIN/INT_MAX to -0.5/0.5 */
      85             : #define LFG_SCALE (1.0f / (2.0f * INT32_MAX))
      86             : 
      87             : /* noise shaping coefficients */
      88             : 
      89             : static const float ns_48_coef_b[4] = {
      90             :     2.2374f, -0.7339f, -0.1251f, -0.6033f
      91             : };
      92             : 
      93             : static const float ns_48_coef_a[4] = {
      94             :     0.9030f, 0.0116f, -0.5853f, -0.2571f
      95             : };
      96             : 
      97             : static const float ns_44_coef_b[4] = {
      98             :     2.2061f, -0.4707f, -0.2534f, -0.6213f
      99             : };
     100             : 
     101             : static const float ns_44_coef_a[4] = {
     102             :     1.0587f, 0.0676f, -0.6054f, -0.2738f
     103             : };
     104             : 
     105           0 : static void dither_int_to_float_rectangular_c(float *dst, int *src, int len)
     106             : {
     107             :     int i;
     108           0 :     for (i = 0; i < len; i++)
     109           0 :         dst[i] = src[i] * LFG_SCALE;
     110           0 : }
     111             : 
     112           0 : static void dither_int_to_float_triangular_c(float *dst, int *src0, int len)
     113             : {
     114             :     int i;
     115           0 :     int *src1  = src0 + len;
     116             : 
     117           0 :     for (i = 0; i < len; i++) {
     118           0 :         float r = src0[i] * LFG_SCALE;
     119           0 :         r      += src1[i] * LFG_SCALE;
     120           0 :         dst[i]  = r;
     121             :     }
     122           0 : }
     123             : 
     124           0 : static void quantize_c(int16_t *dst, const float *src, float *dither, int len)
     125             : {
     126             :     int i;
     127           0 :     for (i = 0; i < len; i++)
     128           0 :         dst[i] = av_clip_int16(lrintf(src[i] * S16_SCALE + dither[i]));
     129           0 : }
     130             : 
     131             : #define SQRT_1_6 0.40824829046386301723f
     132             : 
     133           0 : static void dither_highpass_filter(float *src, int len)
     134             : {
     135             :     int i;
     136             : 
     137             :     /* filter is from libswresample in FFmpeg */
     138           0 :     for (i = 0; i < len - 2; i++)
     139           0 :         src[i] = (-src[i] + 2 * src[i + 1] - src[i + 2]) * SQRT_1_6;
     140           0 : }
     141             : 
     142           0 : static int generate_dither_noise(DitherContext *c, DitherState *state,
     143             :                                  int min_samples)
     144             : {
     145             :     int i;
     146           0 :     int nb_samples  = FFALIGN(min_samples, 16) + 16;
     147           0 :     int buf_samples = nb_samples *
     148           0 :                       (c->method == AV_RESAMPLE_DITHER_RECTANGULAR ? 1 : 2);
     149             :     unsigned int *noise_buf_ui;
     150             : 
     151           0 :     av_freep(&state->noise_buf);
     152           0 :     state->noise_buf_size = state->noise_buf_ptr = 0;
     153             : 
     154           0 :     state->noise_buf = av_malloc(buf_samples * sizeof(*state->noise_buf));
     155           0 :     if (!state->noise_buf)
     156           0 :         return AVERROR(ENOMEM);
     157           0 :     state->noise_buf_size = FFALIGN(min_samples, 16);
     158           0 :     noise_buf_ui          = (unsigned int *)state->noise_buf;
     159             : 
     160           0 :     av_lfg_init(&state->lfg, state->seed);
     161           0 :     for (i = 0; i < buf_samples; i++)
     162           0 :         noise_buf_ui[i] = av_lfg_get(&state->lfg);
     163             : 
     164           0 :     c->ddsp.dither_int_to_float(state->noise_buf, noise_buf_ui, nb_samples);
     165             : 
     166           0 :     if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_HP)
     167           0 :         dither_highpass_filter(state->noise_buf, nb_samples);
     168             : 
     169           0 :     return 0;
     170             : }
     171             : 
     172           0 : static void quantize_triangular_ns(DitherContext *c, DitherState *state,
     173             :                                    int16_t *dst, const float *src,
     174             :                                    int nb_samples)
     175             : {
     176             :     int i, j;
     177           0 :     float *dither = &state->noise_buf[state->noise_buf_ptr];
     178             : 
     179           0 :     if (state->mute > c->mute_reset_threshold)
     180           0 :         memset(state->dither_a, 0, sizeof(state->dither_a));
     181             : 
     182           0 :     for (i = 0; i < nb_samples; i++) {
     183           0 :         float err = 0;
     184           0 :         float sample = src[i] * S16_SCALE;
     185             : 
     186           0 :         for (j = 0; j < 4; j++) {
     187           0 :             err += c->ns_coef_b[j] * state->dither_b[j] -
     188           0 :                    c->ns_coef_a[j] * state->dither_a[j];
     189             :         }
     190           0 :         for (j = 3; j > 0; j--) {
     191           0 :             state->dither_a[j] = state->dither_a[j - 1];
     192           0 :             state->dither_b[j] = state->dither_b[j - 1];
     193             :         }
     194           0 :         state->dither_a[0] = err;
     195           0 :         sample -= err;
     196             : 
     197           0 :         if (state->mute > c->mute_dither_threshold) {
     198           0 :             dst[i]             = av_clip_int16(lrintf(sample));
     199           0 :             state->dither_b[0] = 0;
     200             :         } else {
     201           0 :             dst[i]             = av_clip_int16(lrintf(sample + dither[i]));
     202           0 :             state->dither_b[0] = av_clipf(dst[i] - sample, -1.5f, 1.5f);
     203             :         }
     204             : 
     205           0 :         state->mute++;
     206           0 :         if (src[i])
     207           0 :             state->mute = 0;
     208             :     }
     209           0 : }
     210             : 
     211           0 : static int convert_samples(DitherContext *c, int16_t **dst, float * const *src,
     212             :                            int channels, int nb_samples)
     213             : {
     214             :     int ch, ret;
     215           0 :     int aligned_samples = FFALIGN(nb_samples, 16);
     216             : 
     217           0 :     for (ch = 0; ch < channels; ch++) {
     218           0 :         DitherState *state = &c->state[ch];
     219             : 
     220           0 :         if (state->noise_buf_size < aligned_samples) {
     221           0 :             ret = generate_dither_noise(c, state, nb_samples);
     222           0 :             if (ret < 0)
     223           0 :                 return ret;
     224           0 :         } else if (state->noise_buf_size - state->noise_buf_ptr < aligned_samples) {
     225           0 :             state->noise_buf_ptr = 0;
     226             :         }
     227             : 
     228           0 :         if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
     229           0 :             quantize_triangular_ns(c, state, dst[ch], src[ch], nb_samples);
     230             :         } else {
     231           0 :             c->quantize(dst[ch], src[ch],
     232           0 :                         &state->noise_buf[state->noise_buf_ptr],
     233           0 :                         FFALIGN(nb_samples, c->samples_align));
     234             :         }
     235             : 
     236           0 :         state->noise_buf_ptr += aligned_samples;
     237             :     }
     238             : 
     239           0 :     return 0;
     240             : }
     241             : 
     242           0 : int ff_convert_dither(DitherContext *c, AudioData *dst, AudioData *src)
     243             : {
     244             :     int ret;
     245             :     AudioData *flt_data;
     246             : 
     247             :     /* output directly to dst if it is planar */
     248           0 :     if (dst->sample_fmt == AV_SAMPLE_FMT_S16P)
     249           0 :         c->s16_data = dst;
     250             :     else {
     251             :         /* make sure s16_data is large enough for the output */
     252           0 :         ret = ff_audio_data_realloc(c->s16_data, src->nb_samples);
     253           0 :         if (ret < 0)
     254           0 :             return ret;
     255             :     }
     256             : 
     257           0 :     if (src->sample_fmt != AV_SAMPLE_FMT_FLTP || c->apply_map) {
     258             :         /* make sure flt_data is large enough for the input */
     259           0 :         ret = ff_audio_data_realloc(c->flt_data, src->nb_samples);
     260           0 :         if (ret < 0)
     261           0 :             return ret;
     262           0 :         flt_data = c->flt_data;
     263             :     }
     264             : 
     265           0 :     if (src->sample_fmt != AV_SAMPLE_FMT_FLTP) {
     266             :         /* convert input samples to fltp and scale to s16 range */
     267           0 :         ret = ff_audio_convert(c->ac_in, flt_data, src);
     268           0 :         if (ret < 0)
     269           0 :             return ret;
     270           0 :     } else if (c->apply_map) {
     271           0 :         ret = ff_audio_data_copy(flt_data, src, c->ch_map_info);
     272           0 :         if (ret < 0)
     273           0 :             return ret;
     274             :     } else {
     275           0 :         flt_data = src;
     276             :     }
     277             : 
     278             :     /* check alignment and padding constraints */
     279           0 :     if (c->method != AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
     280           0 :         int ptr_align     = FFMIN(flt_data->ptr_align,     c->s16_data->ptr_align);
     281           0 :         int samples_align = FFMIN(flt_data->samples_align, c->s16_data->samples_align);
     282           0 :         int aligned_len   = FFALIGN(src->nb_samples, c->ddsp.samples_align);
     283             : 
     284           0 :         if (!(ptr_align % c->ddsp.ptr_align) && samples_align >= aligned_len) {
     285           0 :             c->quantize      = c->ddsp.quantize;
     286           0 :             c->samples_align = c->ddsp.samples_align;
     287             :         } else {
     288           0 :             c->quantize      = quantize_c;
     289           0 :             c->samples_align = 1;
     290             :         }
     291             :     }
     292             : 
     293           0 :     ret = convert_samples(c, (int16_t **)c->s16_data->data,
     294           0 :                           (float * const *)flt_data->data, src->channels,
     295             :                           src->nb_samples);
     296           0 :     if (ret < 0)
     297           0 :         return ret;
     298             : 
     299           0 :     c->s16_data->nb_samples = src->nb_samples;
     300             : 
     301             :     /* interleave output to dst if needed */
     302           0 :     if (dst->sample_fmt == AV_SAMPLE_FMT_S16) {
     303           0 :         ret = ff_audio_convert(c->ac_out, dst, c->s16_data);
     304           0 :         if (ret < 0)
     305           0 :             return ret;
     306             :     } else
     307           0 :         c->s16_data = NULL;
     308             : 
     309           0 :     return 0;
     310             : }
     311             : 
     312           0 : void ff_dither_free(DitherContext **cp)
     313             : {
     314           0 :     DitherContext *c = *cp;
     315             :     int ch;
     316             : 
     317           0 :     if (!c)
     318           0 :         return;
     319           0 :     ff_audio_data_free(&c->flt_data);
     320           0 :     ff_audio_data_free(&c->s16_data);
     321           0 :     ff_audio_convert_free(&c->ac_in);
     322           0 :     ff_audio_convert_free(&c->ac_out);
     323           0 :     for (ch = 0; ch < c->channels; ch++)
     324           0 :         av_free(c->state[ch].noise_buf);
     325           0 :     av_free(c->state);
     326           0 :     av_freep(cp);
     327             : }
     328             : 
     329           0 : static av_cold void dither_init(DitherDSPContext *ddsp,
     330             :                                 enum AVResampleDitherMethod method)
     331             : {
     332           0 :     ddsp->quantize      = quantize_c;
     333           0 :     ddsp->ptr_align     = 1;
     334           0 :     ddsp->samples_align = 1;
     335             : 
     336           0 :     if (method == AV_RESAMPLE_DITHER_RECTANGULAR)
     337           0 :         ddsp->dither_int_to_float = dither_int_to_float_rectangular_c;
     338             :     else
     339           0 :         ddsp->dither_int_to_float = dither_int_to_float_triangular_c;
     340             : 
     341             :     if (ARCH_X86)
     342           0 :         ff_dither_init_x86(ddsp, method);
     343           0 : }
     344             : 
     345           0 : DitherContext *ff_dither_alloc(AVAudioResampleContext *avr,
     346             :                                enum AVSampleFormat out_fmt,
     347             :                                enum AVSampleFormat in_fmt,
     348             :                                int channels, int sample_rate, int apply_map)
     349             : {
     350             :     AVLFG seed_gen;
     351             :     DitherContext *c;
     352             :     int ch;
     353             : 
     354           0 :     if (av_get_packed_sample_fmt(out_fmt) != AV_SAMPLE_FMT_S16 ||
     355           0 :         av_get_bytes_per_sample(in_fmt) <= 2) {
     356           0 :         av_log(avr, AV_LOG_ERROR, "dithering %s to %s is not supported\n",
     357             :                av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt));
     358           0 :         return NULL;
     359             :     }
     360             : 
     361           0 :     c = av_mallocz(sizeof(*c));
     362           0 :     if (!c)
     363           0 :         return NULL;
     364             : 
     365           0 :     c->apply_map = apply_map;
     366           0 :     if (apply_map)
     367           0 :         c->ch_map_info = &avr->ch_map_info;
     368             : 
     369           0 :     if (avr->dither_method == AV_RESAMPLE_DITHER_TRIANGULAR_NS &&
     370           0 :         sample_rate != 48000 && sample_rate != 44100) {
     371           0 :         av_log(avr, AV_LOG_WARNING, "sample rate must be 48000 or 44100 Hz "
     372             :                "for triangular_ns dither. using triangular_hp instead.\n");
     373           0 :         avr->dither_method = AV_RESAMPLE_DITHER_TRIANGULAR_HP;
     374             :     }
     375           0 :     c->method = avr->dither_method;
     376           0 :     dither_init(&c->ddsp, c->method);
     377             : 
     378           0 :     if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
     379           0 :         if (sample_rate == 48000) {
     380           0 :             c->ns_coef_b = ns_48_coef_b;
     381           0 :             c->ns_coef_a = ns_48_coef_a;
     382             :         } else {
     383           0 :             c->ns_coef_b = ns_44_coef_b;
     384           0 :             c->ns_coef_a = ns_44_coef_a;
     385             :         }
     386             :     }
     387             : 
     388             :     /* Either s16 or s16p output format is allowed, but s16p is used
     389             :        internally, so we need to use a temp buffer and interleave if the output
     390             :        format is s16 */
     391           0 :     if (out_fmt != AV_SAMPLE_FMT_S16P) {
     392           0 :         c->s16_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_S16P,
     393             :                                           "dither s16 buffer");
     394           0 :         if (!c->s16_data)
     395           0 :             goto fail;
     396             : 
     397           0 :         c->ac_out = ff_audio_convert_alloc(avr, out_fmt, AV_SAMPLE_FMT_S16P,
     398             :                                            channels, sample_rate, 0);
     399           0 :         if (!c->ac_out)
     400           0 :             goto fail;
     401             :     }
     402             : 
     403           0 :     if (in_fmt != AV_SAMPLE_FMT_FLTP || c->apply_map) {
     404           0 :         c->flt_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_FLTP,
     405             :                                           "dither flt buffer");
     406           0 :         if (!c->flt_data)
     407           0 :             goto fail;
     408             :     }
     409           0 :     if (in_fmt != AV_SAMPLE_FMT_FLTP) {
     410           0 :         c->ac_in = ff_audio_convert_alloc(avr, AV_SAMPLE_FMT_FLTP, in_fmt,
     411           0 :                                           channels, sample_rate, c->apply_map);
     412           0 :         if (!c->ac_in)
     413           0 :             goto fail;
     414             :     }
     415             : 
     416           0 :     c->state = av_mallocz(channels * sizeof(*c->state));
     417           0 :     if (!c->state)
     418           0 :         goto fail;
     419           0 :     c->channels = channels;
     420             : 
     421             :     /* calculate thresholds for turning off dithering during periods of
     422             :        silence to avoid replacing digital silence with quiet dither noise */
     423           0 :     c->mute_dither_threshold = lrintf(sample_rate * MUTE_THRESHOLD_SEC);
     424           0 :     c->mute_reset_threshold  = c->mute_dither_threshold * 4;
     425             : 
     426             :     /* initialize dither states */
     427           0 :     av_lfg_init(&seed_gen, 0xC0FFEE);
     428           0 :     for (ch = 0; ch < channels; ch++) {
     429           0 :         DitherState *state = &c->state[ch];
     430           0 :         state->mute = c->mute_reset_threshold + 1;
     431           0 :         state->seed = av_lfg_get(&seed_gen);
     432           0 :         generate_dither_noise(c, state, FFMAX(32768, sample_rate / 2));
     433             :     }
     434             : 
     435           0 :     return c;
     436             : 
     437             : fail:
     438           0 :     ff_dither_free(&c);
     439           0 :     return NULL;
     440             : }

Generated by: LCOV version 1.13