Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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 
22
 
23
#include "libavutil/avassert.h"
24
#include "libavutil/channel_layout.h"
25
#include "libavutil/opt.h"
26
#include "audio.h"
27
#include "avfilter.h"
28
#include "internal.h"
29
 
30
typedef struct {
31
    const AVClass *class;
32
    double frequency;
33
    double beep_factor;
34
    int samples_per_frame;
35
    int sample_rate;
36
    int64_t duration;
37
    int16_t *sin;
38
    int64_t pts;
39
    uint32_t phi;  ///< current phase of the sine (2pi = 1<<32)
40
    uint32_t dphi; ///< phase increment between two samples
41
    unsigned beep_period;
42
    unsigned beep_index;
43
    unsigned beep_length;
44
    uint32_t phi_beep;  ///< current phase of the beep
45
    uint32_t dphi_beep; ///< phase increment of the beep
46
} SineContext;
47
 
48
#define CONTEXT SineContext
49
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
50
 
51
#define OPT_GENERIC(name, field, def, min, max, descr, type, deffield, ...) \
52
    { name, descr, offsetof(CONTEXT, field), AV_OPT_TYPE_ ## type,          \
53
      { .deffield = def }, min, max, FLAGS, __VA_ARGS__ }
54
 
55
#define OPT_INT(name, field, def, min, max, descr, ...) \
56
    OPT_GENERIC(name, field, def, min, max, descr, INT, i64, __VA_ARGS__)
57
 
58
#define OPT_DBL(name, field, def, min, max, descr, ...) \
59
    OPT_GENERIC(name, field, def, min, max, descr, DOUBLE, dbl, __VA_ARGS__)
60
 
61
#define OPT_DUR(name, field, def, min, max, descr, ...) \
62
    OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
63
 
64
static const AVOption sine_options[] = {
65
    OPT_DBL("frequency",         frequency,            440, 0, DBL_MAX,   "set the sine frequency"),
66
    OPT_DBL("f",                 frequency,            440, 0, DBL_MAX,   "set the sine frequency"),
67
    OPT_DBL("beep_factor",       beep_factor,            0, 0, DBL_MAX,   "set the beep fequency factor"),
68
    OPT_DBL("b",                 beep_factor,            0, 0, DBL_MAX,   "set the beep fequency factor"),
69
    OPT_INT("sample_rate",       sample_rate,        44100, 1, INT_MAX,   "set the sample rate"),
70
    OPT_INT("r",                 sample_rate,        44100, 1, INT_MAX,   "set the sample rate"),
71
    OPT_DUR("duration",          duration,               0, 0, INT64_MAX, "set the audio duration"),
72
    OPT_DUR("d",                 duration,               0, 0, INT64_MAX, "set the audio duration"),
73
    OPT_INT("samples_per_frame", samples_per_frame,   1024, 0, INT_MAX,   "set the number of samples per frame"),
74
    {NULL}
75
};
76
 
77
AVFILTER_DEFINE_CLASS(sine);
78
 
79
#define LOG_PERIOD 15
80
#define AMPLITUDE 4095
81
#define AMPLITUDE_SHIFT 3
82
 
83
static void make_sin_table(int16_t *sin)
84
{
85
    unsigned half_pi = 1 << (LOG_PERIOD - 2);
86
    unsigned ampls = AMPLITUDE << AMPLITUDE_SHIFT;
87
    uint64_t unit2 = (uint64_t)(ampls * ampls) << 32;
88
    unsigned step, i, c, s, k, new_k, n2;
89
 
90
    /* Principle: if u = exp(i*a1) and v = exp(i*a2), then
91
       exp(i*(a1+a2)/2) = (u+v) / length(u+v) */
92
    sin[0] = 0;
93
    sin[half_pi] = ampls;
94
    for (step = half_pi; step > 1; step /= 2) {
95
        /* k = (1 << 16) * amplitude / length(u+v)
96
           In exact values, k is constant at a given step */
97
        k = 0x10000;
98
        for (i = 0; i < half_pi / 2; i += step) {
99
            s = sin[i] + sin[i + step];
100
            c = sin[half_pi - i] + sin[half_pi - i - step];
101
            n2 = s * s + c * c;
102
            /* Newton's method to solve n² * k² = unit² */
103
            while (1) {
104
                new_k = (k + unit2 / ((uint64_t)k * n2) + 1) >> 1;
105
                if (k == new_k)
106
                    break;
107
                k = new_k;
108
            }
109
            sin[i + step / 2] = (k * s + 0x7FFF) >> 16;
110
            sin[half_pi - i - step / 2] = (k * c + 0x8000) >> 16;
111
        }
112
    }
113
    /* Unshift amplitude */
114
    for (i = 0; i <= half_pi; i++)
115
        sin[i] = (sin[i] + (1 << (AMPLITUDE_SHIFT - 1))) >> AMPLITUDE_SHIFT;
116
    /* Use symmetries to fill the other three quarters */
117
    for (i = 0; i < half_pi; i++)
118
        sin[half_pi * 2 - i] = sin[i];
119
    for (i = 0; i < 2 * half_pi; i++)
120
        sin[i + 2 * half_pi] = -sin[i];
121
}
122
 
123
static av_cold int init(AVFilterContext *ctx)
124
{
125
    SineContext *sine = ctx->priv;
126
 
127
    if (!(sine->sin = av_malloc(sizeof(*sine->sin) << LOG_PERIOD)))
128
        return AVERROR(ENOMEM);
129
    sine->dphi = ldexp(sine->frequency, 32) / sine->sample_rate + 0.5;
130
    make_sin_table(sine->sin);
131
 
132
    if (sine->beep_factor) {
133
        sine->beep_period = sine->sample_rate;
134
        sine->beep_length = sine->beep_period / 25;
135
        sine->dphi_beep = ldexp(sine->beep_factor * sine->frequency, 32) /
136
                          sine->sample_rate + 0.5;
137
    }
138
 
139
    return 0;
140
}
141
 
142
static av_cold void uninit(AVFilterContext *ctx)
143
{
144
    SineContext *sine = ctx->priv;
145
 
146
    av_freep(&sine->sin);
147
}
148
 
149
static av_cold int query_formats(AVFilterContext *ctx)
150
{
151
    SineContext *sine = ctx->priv;
152
    static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 };
153
    int sample_rates[] = { sine->sample_rate, -1 };
154
    static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16,
155
                                                       AV_SAMPLE_FMT_NONE };
156
 
157
    ff_set_common_formats (ctx, ff_make_format_list(sample_fmts));
158
    ff_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
159
    ff_set_common_samplerates(ctx, ff_make_format_list(sample_rates));
160
    return 0;
161
}
162
 
163
static av_cold int config_props(AVFilterLink *outlink)
164
{
165
    SineContext *sine = outlink->src->priv;
166
    sine->duration = av_rescale(sine->duration, sine->sample_rate, AV_TIME_BASE);
167
    return 0;
168
}
169
 
170
static int request_frame(AVFilterLink *outlink)
171
{
172
    SineContext *sine = outlink->src->priv;
173
    AVFrame *frame;
174
    int i, nb_samples = sine->samples_per_frame;
175
    int16_t *samples;
176
 
177
    if (sine->duration) {
178
        nb_samples = FFMIN(nb_samples, sine->duration - sine->pts);
179
        av_assert1(nb_samples >= 0);
180
        if (!nb_samples)
181
            return AVERROR_EOF;
182
    }
183
    if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
184
        return AVERROR(ENOMEM);
185
    samples = (int16_t *)frame->data[0];
186
 
187
    for (i = 0; i < nb_samples; i++) {
188
        samples[i] = sine->sin[sine->phi >> (32 - LOG_PERIOD)];
189
        sine->phi += sine->dphi;
190
        if (sine->beep_index < sine->beep_length) {
191
            samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] << 1;
192
            sine->phi_beep += sine->dphi_beep;
193
        }
194
        if (++sine->beep_index == sine->beep_period)
195
            sine->beep_index = 0;
196
    }
197
 
198
    frame->pts = sine->pts;
199
    sine->pts += nb_samples;
200
    return ff_filter_frame(outlink, frame);
201
}
202
 
203
static const AVFilterPad sine_outputs[] = {
204
    {
205
        .name          = "default",
206
        .type          = AVMEDIA_TYPE_AUDIO,
207
        .request_frame = request_frame,
208
        .config_props  = config_props,
209
    },
210
    { NULL }
211
};
212
 
213
AVFilter avfilter_asrc_sine = {
214
    .name          = "sine",
215
    .description   = NULL_IF_CONFIG_SMALL("Generate sine wave audio signal."),
216
    .query_formats = query_formats,
217
    .init          = init,
218
    .uninit        = uninit,
219
    .priv_size     = sizeof(SineContext),
220
    .inputs        = NULL,
221
    .outputs       = sine_outputs,
222
    .priv_class    = &sine_class,
223
};