]> git.sesse.net Git - ffmpeg/blob - libavresample/tests/avresample.c
avutil/cpu: Remove deprecated functions
[ffmpeg] / libavresample / tests / avresample.c
1 /*
2  * Copyright (c) 2002 Fabrice Bellard
3  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <stdint.h>
23 #include <stdio.h>
24
25 #include "libavutil/avstring.h"
26 #include "libavutil/common.h"
27 #include "libavutil/lfg.h"
28 #include "libavutil/libm.h"
29 #include "libavutil/log.h"
30 #include "libavutil/mem.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/samplefmt.h"
33
34 #include "libavresample/avresample.h"
35
36 static double dbl_rand(AVLFG *lfg)
37 {
38     return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
39 }
40
41 #define PUT_FUNC(name, fmt, type, expr)                                     \
42 static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
43                                 int channels, int sample, int ch,           \
44                                 double v_dbl)                               \
45 {                                                                           \
46     type v = expr;                                                          \
47     type **out = (type **)data;                                             \
48     if (av_sample_fmt_is_planar(sample_fmt))                                \
49         out[ch][sample] = v;                                                \
50     else                                                                    \
51         out[0][sample * channels + ch] = v;                                 \
52 }
53
54 PUT_FUNC(u8,  AV_SAMPLE_FMT_U8,  uint8_t, av_clip_uint8 ( lrint(v_dbl * (1  <<  7)) + 128))
55 PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1  << 15))))
56 PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
57 PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float,   v_dbl)
58 PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double,  v_dbl)
59
60 static void put_sample(void **data, enum AVSampleFormat sample_fmt,
61                        int channels, int sample, int ch, double v_dbl)
62 {
63     switch (av_get_packed_sample_fmt(sample_fmt)) {
64     case AV_SAMPLE_FMT_U8:
65         put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
66         break;
67     case AV_SAMPLE_FMT_S16:
68         put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
69         break;
70     case AV_SAMPLE_FMT_S32:
71         put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
72         break;
73     case AV_SAMPLE_FMT_FLT:
74         put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
75         break;
76     case AV_SAMPLE_FMT_DBL:
77         put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
78         break;
79     }
80 }
81
82 static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
83                      int channels, int sample_rate, int nb_samples)
84 {
85     int i, ch, k;
86     double v, f, a, ampa;
87     double tabf1[AVRESAMPLE_MAX_CHANNELS];
88     double tabf2[AVRESAMPLE_MAX_CHANNELS];
89     double taba[AVRESAMPLE_MAX_CHANNELS];
90
91 #define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
92
93     k = 0;
94
95     /* 1 second of single freq sine at 1000 Hz */
96     a = 0;
97     for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
98         v = sin(a) * 0.30;
99         for (ch = 0; ch < channels; ch++)
100             PUT_SAMPLE
101         a += M_PI * 1000.0 * 2.0 / sample_rate;
102     }
103
104     /* 1 second of varying frequency between 100 and 10000 Hz */
105     a = 0;
106     for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
107         v = sin(a) * 0.30;
108         for (ch = 0; ch < channels; ch++)
109             PUT_SAMPLE
110         f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
111         a += M_PI * f * 2.0 / sample_rate;
112     }
113
114     /* 0.5 second of low amplitude white noise */
115     for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
116         v = dbl_rand(rnd) * 0.30;
117         for (ch = 0; ch < channels; ch++)
118             PUT_SAMPLE
119     }
120
121     /* 0.5 second of high amplitude white noise */
122     for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
123         v = dbl_rand(rnd);
124         for (ch = 0; ch < channels; ch++)
125             PUT_SAMPLE
126     }
127
128     /* 1 second of unrelated ramps for each channel */
129     for (ch = 0; ch < channels; ch++) {
130         taba[ch]  = 0;
131         tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
132         tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
133     }
134     for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
135         for (ch = 0; ch < channels; ch++) {
136             v = sin(taba[ch]) * 0.30;
137             PUT_SAMPLE
138             f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
139             taba[ch] += M_PI * f * 2.0 / sample_rate;
140         }
141     }
142
143     /* 2 seconds of 500 Hz with varying volume */
144     a    = 0;
145     ampa = 0;
146     for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
147         for (ch = 0; ch < channels; ch++) {
148             double amp = (1.0 + sin(ampa)) * 0.15;
149             if (ch & 1)
150                 amp = 0.30 - amp;
151             v = sin(a) * amp;
152             PUT_SAMPLE
153             a    += M_PI * 500.0 * 2.0 / sample_rate;
154             ampa += M_PI *  2.0 / sample_rate;
155         }
156     }
157 }
158
159 /* formats, rates, and layouts are ordered for priority in testing.
160    e.g. 'avresample-test 4 2 2' will test all input/output combinations of
161    S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
162
163 static const enum AVSampleFormat formats[] = {
164     AV_SAMPLE_FMT_S16,
165     AV_SAMPLE_FMT_FLTP,
166     AV_SAMPLE_FMT_S16P,
167     AV_SAMPLE_FMT_FLT,
168     AV_SAMPLE_FMT_S32P,
169     AV_SAMPLE_FMT_S32,
170     AV_SAMPLE_FMT_U8P,
171     AV_SAMPLE_FMT_U8,
172     AV_SAMPLE_FMT_DBLP,
173     AV_SAMPLE_FMT_DBL,
174 };
175
176 static const int rates[] = {
177     48000,
178     44100,
179     16000
180 };
181
182 static const uint64_t layouts[] = {
183     AV_CH_LAYOUT_STEREO,
184     AV_CH_LAYOUT_MONO,
185     AV_CH_LAYOUT_5POINT1,
186     AV_CH_LAYOUT_7POINT1,
187 };
188
189 int main(int argc, char **argv)
190 {
191     AVAudioResampleContext *s;
192     AVLFG rnd;
193     int ret = 0;
194     uint8_t *in_buf = NULL;
195     uint8_t *out_buf = NULL;
196     unsigned int in_buf_size;
197     unsigned int out_buf_size;
198     uint8_t  *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
199     uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
200     int in_linesize;
201     int out_linesize;
202     uint64_t in_ch_layout;
203     int in_channels;
204     enum AVSampleFormat in_fmt;
205     int in_rate;
206     uint64_t out_ch_layout;
207     int out_channels;
208     enum AVSampleFormat out_fmt;
209     int out_rate;
210     int num_formats, num_rates, num_layouts;
211     int i, j, k, l, m, n;
212
213     num_formats = 2;
214     num_rates   = 2;
215     num_layouts = 2;
216     if (argc > 1) {
217         if (!av_strncasecmp(argv[1], "-h", 3)) {
218             av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
219                    "[<num sample rates> [<num channel layouts>]]]\n"
220                    "Default is 2 2 2\n");
221             return 0;
222         }
223         num_formats = strtol(argv[1], NULL, 0);
224         num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
225     }
226     if (argc > 2) {
227         num_rates = strtol(argv[2], NULL, 0);
228         num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
229     }
230     if (argc > 3) {
231         num_layouts = strtol(argv[3], NULL, 0);
232         num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
233     }
234
235     av_log_set_level(AV_LOG_DEBUG);
236
237     av_lfg_init(&rnd, 0xC0FFEE);
238
239     in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
240                                              AV_SAMPLE_FMT_DBLP, 0);
241     out_buf_size = in_buf_size;
242
243     in_buf = av_malloc(in_buf_size);
244     if (!in_buf)
245         goto end;
246     out_buf = av_malloc(out_buf_size);
247     if (!out_buf)
248         goto end;
249
250     s = avresample_alloc_context();
251     if (!s) {
252         av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
253         ret = 1;
254         goto end;
255     }
256
257     for (i = 0; i < num_formats; i++) {
258         in_fmt = formats[i];
259         for (k = 0; k < num_layouts; k++) {
260             in_ch_layout = layouts[k];
261             in_channels  = av_get_channel_layout_nb_channels(in_ch_layout);
262             for (m = 0; m < num_rates; m++) {
263                 in_rate = rates[m];
264
265                 ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
266                                              in_channels, in_rate * 6,
267                                              in_fmt, 0);
268                 if (ret < 0) {
269                     av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
270                     goto end;
271                 }
272                 audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
273
274                 for (j = 0; j < num_formats; j++) {
275                     out_fmt = formats[j];
276                     for (l = 0; l < num_layouts; l++) {
277                         out_ch_layout = layouts[l];
278                         out_channels  = av_get_channel_layout_nb_channels(out_ch_layout);
279                         for (n = 0; n < num_rates; n++) {
280                             out_rate = rates[n];
281
282                             av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
283                                    av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
284                                    in_channels, out_channels, in_rate, out_rate);
285
286                             ret = av_samples_fill_arrays(out_data, &out_linesize,
287                                                          out_buf, out_channels,
288                                                          out_rate * 6, out_fmt, 0);
289                             if (ret < 0) {
290                                 av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
291                                 goto end;
292                             }
293
294                             av_opt_set_int(s, "in_channel_layout",  in_ch_layout,  0);
295                             av_opt_set_int(s, "in_sample_fmt",      in_fmt,        0);
296                             av_opt_set_int(s, "in_sample_rate",     in_rate,       0);
297                             av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
298                             av_opt_set_int(s, "out_sample_fmt",     out_fmt,       0);
299                             av_opt_set_int(s, "out_sample_rate",    out_rate,      0);
300
301                             av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
302
303                             ret = avresample_open(s);
304                             if (ret < 0) {
305                                 av_log(s, AV_LOG_ERROR, "Error opening context\n");
306                                 goto end;
307                             }
308
309                             ret = avresample_convert(s, out_data, out_linesize, out_rate * 6,
310                                                          in_data,  in_linesize,  in_rate * 6);
311                             if (ret < 0) {
312                                 char errbuf[256];
313                                 av_strerror(ret, errbuf, sizeof(errbuf));
314                                 av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
315                                 goto end;
316                             }
317                             av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
318                                    in_rate * 6, ret);
319                             if (avresample_get_delay(s) > 0)
320                                 av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
321                                        avresample_get_delay(s));
322                             if (avresample_available(s) > 0)
323                                 av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
324                                        avresample_available(s));
325                             av_log(NULL, AV_LOG_INFO, "\n");
326
327                             avresample_close(s);
328                         }
329                     }
330                 }
331             }
332         }
333     }
334
335     ret = 0;
336
337 end:
338     av_freep(&in_buf);
339     av_freep(&out_buf);
340     avresample_free(&s);
341     return ret;
342 }