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