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