LCOV - code coverage report
Current view: top level - src/libavfilter - asrc_sine.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 89 99 89.9 %
Date: 2017-07-21 15:41:20 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Nicolas George
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public License
       8             :  * as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
      18             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <float.h>
      22             : 
      23             : #include "libavutil/avassert.h"
      24             : #include "libavutil/channel_layout.h"
      25             : #include "libavutil/eval.h"
      26             : #include "libavutil/opt.h"
      27             : #include "audio.h"
      28             : #include "avfilter.h"
      29             : #include "internal.h"
      30             : 
      31             : typedef struct SineContext {
      32             :     const AVClass *class;
      33             :     double frequency;
      34             :     double beep_factor;
      35             :     char *samples_per_frame;
      36             :     AVExpr *samples_per_frame_expr;
      37             :     int sample_rate;
      38             :     int64_t duration;
      39             :     int16_t *sin;
      40             :     int64_t pts;
      41             :     uint32_t phi;  ///< current phase of the sine (2pi = 1<<32)
      42             :     uint32_t dphi; ///< phase increment between two samples
      43             :     unsigned beep_period;
      44             :     unsigned beep_index;
      45             :     unsigned beep_length;
      46             :     uint32_t phi_beep;  ///< current phase of the beep
      47             :     uint32_t dphi_beep; ///< phase increment of the beep
      48             : } SineContext;
      49             : 
      50             : #define CONTEXT SineContext
      51             : #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
      52             : 
      53             : #define OPT_GENERIC(name, field, def, min, max, descr, type, deffield, ...) \
      54             :     { name, descr, offsetof(CONTEXT, field), AV_OPT_TYPE_ ## type,          \
      55             :       { .deffield = def }, min, max, FLAGS, __VA_ARGS__ }
      56             : 
      57             : #define OPT_INT(name, field, def, min, max, descr, ...) \
      58             :     OPT_GENERIC(name, field, def, min, max, descr, INT, i64, __VA_ARGS__)
      59             : 
      60             : #define OPT_DBL(name, field, def, min, max, descr, ...) \
      61             :     OPT_GENERIC(name, field, def, min, max, descr, DOUBLE, dbl, __VA_ARGS__)
      62             : 
      63             : #define OPT_DUR(name, field, def, min, max, descr, ...) \
      64             :     OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
      65             : 
      66             : #define OPT_STR(name, field, def, min, max, descr, ...) \
      67             :     OPT_GENERIC(name, field, def, min, max, descr, STRING, str, __VA_ARGS__)
      68             : 
      69             : static const AVOption sine_options[] = {
      70             :     OPT_DBL("frequency",         frequency,            440, 0, DBL_MAX,   "set the sine frequency",),
      71             :     OPT_DBL("f",                 frequency,            440, 0, DBL_MAX,   "set the sine frequency",),
      72             :     OPT_DBL("beep_factor",       beep_factor,            0, 0, DBL_MAX,   "set the beep frequency factor",),
      73             :     OPT_DBL("b",                 beep_factor,            0, 0, DBL_MAX,   "set the beep frequency factor",),
      74             :     OPT_INT("sample_rate",       sample_rate,        44100, 1, INT_MAX,   "set the sample rate",),
      75             :     OPT_INT("r",                 sample_rate,        44100, 1, INT_MAX,   "set the sample rate",),
      76             :     OPT_DUR("duration",          duration,               0, 0, INT64_MAX, "set the audio duration",),
      77             :     OPT_DUR("d",                 duration,               0, 0, INT64_MAX, "set the audio duration",),
      78             :     OPT_STR("samples_per_frame", samples_per_frame, "1024", 0, 0,         "set the number of samples per frame",),
      79             :     {NULL}
      80             : };
      81             : 
      82             : AVFILTER_DEFINE_CLASS(sine);
      83             : 
      84             : #define LOG_PERIOD 15
      85             : #define AMPLITUDE 4095
      86             : #define AMPLITUDE_SHIFT 3
      87             : 
      88           7 : static void make_sin_table(int16_t *sin)
      89             : {
      90           7 :     unsigned half_pi = 1 << (LOG_PERIOD - 2);
      91           7 :     unsigned ampls = AMPLITUDE << AMPLITUDE_SHIFT;
      92           7 :     uint64_t unit2 = (uint64_t)(ampls * ampls) << 32;
      93             :     unsigned step, i, c, s, k, new_k, n2;
      94             : 
      95             :     /* Principle: if u = exp(i*a1) and v = exp(i*a2), then
      96             :        exp(i*(a1+a2)/2) = (u+v) / length(u+v) */
      97           7 :     sin[0] = 0;
      98           7 :     sin[half_pi] = ampls;
      99          98 :     for (step = half_pi; step > 1; step /= 2) {
     100             :         /* k = (1 << 16) * amplitude / length(u+v)
     101             :            In exact values, k is constant at a given step */
     102          91 :         k = 0x10000;
     103       28763 :         for (i = 0; i < half_pi / 2; i += step) {
     104       28672 :             s = sin[i] + sin[i + step];
     105       28672 :             c = sin[half_pi - i] + sin[half_pi - i - step];
     106       28672 :             n2 = s * s + c * c;
     107             :             /* Newton's method to solve n² * k² = unit² */
     108             :             while (1) {
     109       38304 :                 new_k = (k + unit2 / ((uint64_t)k * n2) + 1) >> 1;
     110       33488 :                 if (k == new_k)
     111       28672 :                     break;
     112        4816 :                 k = new_k;
     113             :             }
     114       28672 :             sin[i + step / 2] = (k * s + 0x7FFF) >> 16;
     115       28672 :             sin[half_pi - i - step / 2] = (k * c + 0x8000) >> 16;
     116             :         }
     117             :     }
     118             :     /* Unshift amplitude */
     119       57358 :     for (i = 0; i <= half_pi; i++)
     120       57351 :         sin[i] = (sin[i] + (1 << (AMPLITUDE_SHIFT - 1))) >> AMPLITUDE_SHIFT;
     121             :     /* Use symmetries to fill the other three quarters */
     122       57351 :     for (i = 0; i < half_pi; i++)
     123       57344 :         sin[half_pi * 2 - i] = sin[i];
     124      114695 :     for (i = 0; i < 2 * half_pi; i++)
     125      114688 :         sin[i + 2 * half_pi] = -sin[i];
     126           7 : }
     127             : 
     128             : static const char *const var_names[] = {
     129             :     "n",
     130             :     "pts",
     131             :     "t",
     132             :     "TB",
     133             :     NULL
     134             : };
     135             : 
     136             : enum {
     137             :     VAR_N,
     138             :     VAR_PTS,
     139             :     VAR_T,
     140             :     VAR_TB,
     141             :     VAR_VARS_NB
     142             : };
     143             : 
     144           7 : static av_cold int init(AVFilterContext *ctx)
     145             : {
     146             :     int ret;
     147           7 :     SineContext *sine = ctx->priv;
     148             : 
     149           7 :     if (!(sine->sin = av_malloc(sizeof(*sine->sin) << LOG_PERIOD)))
     150           0 :         return AVERROR(ENOMEM);
     151           7 :     sine->dphi = ldexp(sine->frequency, 32) / sine->sample_rate + 0.5;
     152           7 :     make_sin_table(sine->sin);
     153             : 
     154           7 :     if (sine->beep_factor) {
     155           6 :         sine->beep_period = sine->sample_rate;
     156           6 :         sine->beep_length = sine->beep_period / 25;
     157          18 :         sine->dphi_beep = ldexp(sine->beep_factor * sine->frequency, 32) /
     158          12 :                           sine->sample_rate + 0.5;
     159             :     }
     160             : 
     161           7 :     ret = av_expr_parse(&sine->samples_per_frame_expr,
     162           7 :                         sine->samples_per_frame, var_names,
     163             :                         NULL, NULL, NULL, NULL, 0, sine);
     164           7 :     if (ret < 0)
     165           0 :         return ret;
     166             : 
     167           7 :     return 0;
     168             : }
     169             : 
     170           7 : static av_cold void uninit(AVFilterContext *ctx)
     171             : {
     172           7 :     SineContext *sine = ctx->priv;
     173             : 
     174           7 :     av_expr_free(sine->samples_per_frame_expr);
     175           7 :     sine->samples_per_frame_expr = NULL;
     176           7 :     av_freep(&sine->sin);
     177           7 : }
     178             : 
     179           4 : static av_cold int query_formats(AVFilterContext *ctx)
     180             : {
     181           4 :     SineContext *sine = ctx->priv;
     182             :     static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 };
     183           4 :     int sample_rates[] = { sine->sample_rate, -1 };
     184             :     static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16,
     185             :                                                        AV_SAMPLE_FMT_NONE };
     186             :     AVFilterFormats *formats;
     187             :     AVFilterChannelLayouts *layouts;
     188             :     int ret;
     189             : 
     190           4 :     formats = ff_make_format_list(sample_fmts);
     191           4 :     if (!formats)
     192           0 :         return AVERROR(ENOMEM);
     193           4 :     ret = ff_set_common_formats (ctx, formats);
     194           4 :     if (ret < 0)
     195           0 :         return ret;
     196             : 
     197           4 :     layouts = avfilter_make_format64_list(chlayouts);
     198           4 :     if (!layouts)
     199           0 :         return AVERROR(ENOMEM);
     200           4 :     ret = ff_set_common_channel_layouts(ctx, layouts);
     201           4 :     if (ret < 0)
     202           0 :         return ret;
     203             : 
     204           4 :     formats = ff_make_format_list(sample_rates);
     205           4 :     if (!formats)
     206           0 :         return AVERROR(ENOMEM);
     207           4 :     return ff_set_common_samplerates(ctx, formats);
     208             : }
     209             : 
     210           4 : static av_cold int config_props(AVFilterLink *outlink)
     211             : {
     212           4 :     SineContext *sine = outlink->src->priv;
     213           4 :     sine->duration = av_rescale(sine->duration, sine->sample_rate, AV_TIME_BASE);
     214           4 :     return 0;
     215             : }
     216             : 
     217         226 : static int request_frame(AVFilterLink *outlink)
     218             : {
     219         226 :     SineContext *sine = outlink->src->priv;
     220             :     AVFrame *frame;
     221         904 :     double values[VAR_VARS_NB] = {
     222         226 :         [VAR_N]   = outlink->frame_count_in,
     223         226 :         [VAR_PTS] = sine->pts,
     224         226 :         [VAR_T]   = sine->pts * av_q2d(outlink->time_base),
     225         226 :         [VAR_TB]  = av_q2d(outlink->time_base),
     226             :     };
     227         226 :     int i, nb_samples = lrint(av_expr_eval(sine->samples_per_frame_expr, values, sine));
     228             :     int16_t *samples;
     229             : 
     230         226 :     if (nb_samples <= 0) {
     231           0 :         av_log(sine, AV_LOG_WARNING, "nb samples expression evaluated to %d, "
     232             :                "defaulting to 1024\n", nb_samples);
     233           0 :         nb_samples = 1024;
     234             :     }
     235             : 
     236         226 :     if (sine->duration) {
     237         226 :         nb_samples = FFMIN(nb_samples, sine->duration - sine->pts);
     238             :         av_assert1(nb_samples >= 0);
     239         226 :         if (!nb_samples)
     240           4 :             return AVERROR_EOF;
     241             :     }
     242         222 :     if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
     243           0 :         return AVERROR(ENOMEM);
     244         222 :     samples = (int16_t *)frame->data[0];
     245             : 
     246      224622 :     for (i = 0; i < nb_samples; i++) {
     247      224400 :         samples[i] = sine->sin[sine->phi >> (32 - LOG_PERIOD)];
     248      224400 :         sine->phi += sine->dphi;
     249      224400 :         if (sine->beep_index < sine->beep_length) {
     250        7056 :             samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] << 1;
     251        7056 :             sine->phi_beep += sine->dphi_beep;
     252             :         }
     253      224400 :         if (++sine->beep_index == sine->beep_period)
     254           4 :             sine->beep_index = 0;
     255             :     }
     256             : 
     257         222 :     frame->pts = sine->pts;
     258         222 :     sine->pts += nb_samples;
     259         222 :     return ff_filter_frame(outlink, frame);
     260             : }
     261             : 
     262             : static const AVFilterPad sine_outputs[] = {
     263             :     {
     264             :         .name          = "default",
     265             :         .type          = AVMEDIA_TYPE_AUDIO,
     266             :         .request_frame = request_frame,
     267             :         .config_props  = config_props,
     268             :     },
     269             :     { NULL }
     270             : };
     271             : 
     272             : AVFilter ff_asrc_sine = {
     273             :     .name          = "sine",
     274             :     .description   = NULL_IF_CONFIG_SMALL("Generate sine wave audio signal."),
     275             :     .query_formats = query_formats,
     276             :     .init          = init,
     277             :     .uninit        = uninit,
     278             :     .priv_size     = sizeof(SineContext),
     279             :     .inputs        = NULL,
     280             :     .outputs       = sine_outputs,
     281             :     .priv_class    = &sine_class,
     282             : };

Generated by: LCOV version 1.13