FFmpeg
avresample.c
Go to the documentation of this file.
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 
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[] = {
174 };
175 
176 static const int rates[] = {
177  48000,
178  44100,
179  16000
180 };
181 
182 static const uint64_t layouts[] = {
187 };
188 
189 int main(int argc, char **argv)
190 {
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 
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 
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",
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",
322  if (avresample_available(s) > 0)
323  av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
325  av_log(NULL, AV_LOG_INFO, "\n");
326 
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 }
formats
formats
Definition: signature.h:48
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:69
avresample_alloc_context
attribute_deprecated AVAudioResampleContext * avresample_alloc_context(void)
Definition: options.c:96
av_clip
#define av_clip
Definition: common.h:122
opt.h
libm.h
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
AV_CH_LAYOUT_MONO
#define AV_CH_LAYOUT_MONO
Definition: channel_layout.h:90
av_samples_fill_arrays
int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, const uint8_t *buf, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)
Fill plane data pointers and linesize for samples with sample format sample_fmt.
Definition: samplefmt.c:151
AVRESAMPLE_MAX_CHANNELS
#define AVRESAMPLE_MAX_CHANNELS
Definition: avresample.h:104
PUT_FUNC
#define PUT_FUNC(name, fmt, type, expr)
Definition: avresample.c:41
AV_SAMPLE_FMT_S32P
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: samplefmt.h:68
data
const char data[16]
Definition: mxf.c:142
avresample.h
sample_rate
sample_rate
Definition: ffmpeg_filter.c:170
avresample_get_delay
attribute_deprecated int avresample_get_delay(AVAudioResampleContext *avr)
Definition: resample.c:438
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
rates
static const int rates[]
Definition: avresample.c:176
AVAudioResampleContext
Definition: internal.h:53
U
#define U(x)
Definition: vp56_arith.h:37
av_strerror
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:105
samplefmt.h
AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_STEREO
Definition: channel_layout.h:91
lrint
#define lrint
Definition: tablegen.h:53
rnd
#define rnd()
Definition: checkasm.h:117
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
avresample_open
attribute_deprecated int avresample_open(AVAudioResampleContext *avr)
Definition: utils.c:36
dbl_rand
static double dbl_rand(AVLFG *lfg)
Definition: avresample.c:36
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_lfg_get
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:53
lfg.h
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
channels
channels
Definition: aptx.h:33
av_get_sample_fmt_name
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
Definition: samplefmt.c:49
f
#define f(width, name)
Definition: cbs_vp9.c:255
int32_t
int32_t
Definition: audio_convert.c:194
layouts
static const uint64_t layouts[]
Definition: avresample.c:182
av_clip_int16
#define av_clip_int16
Definition: common.h:137
NULL
#define NULL
Definition: coverity.c:32
AV_CH_LAYOUT_5POINT1
#define AV_CH_LAYOUT_5POINT1
Definition: channel_layout.h:101
AV_SAMPLE_FMT_U8
AV_SAMPLE_FMT_U8
Definition: audio_convert.c:194
av_get_channel_layout_nb_channels
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
Definition: channel_layout.c:226
av_opt_set_int
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:586
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:225
avresample_free
attribute_deprecated void avresample_free(AVAudioResampleContext **avr)
Definition: utils.c:278
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
AV_SAMPLE_FMT_U8P
@ AV_SAMPLE_FMT_U8P
unsigned 8 bits, planar
Definition: samplefmt.h:66
av_clipl_int32
#define av_clipl_int32
Definition: common.h:140
sample
#define sample
Definition: flacdsp_template.c:44
avresample_convert
attribute_deprecated int avresample_convert(AVAudioResampleContext *avr, uint8_t **output, int out_plane_size, int out_samples, uint8_t *const *input, int in_plane_size, int in_samples)
Definition: utils.c:330
main
int main(int argc, char **argv)
Definition: avresample.c:189
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
M_PI
#define M_PI
Definition: mathematics.h:52
AV_SAMPLE_FMT_S16P
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: samplefmt.h:67
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
PUT_SAMPLE
#define PUT_SAMPLE
avresample_close
attribute_deprecated void avresample_close(AVAudioResampleContext *avr)
Definition: utils.c:262
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:440
i
int i
Definition: input.c:407
log.h
avresample_available
attribute_deprecated int avresample_available(AVAudioResampleContext *avr)
Definition: utils.c:748
common.h
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
AV_CH_LAYOUT_7POINT1
#define AV_CH_LAYOUT_7POINT1
Definition: channel_layout.h:112
uint8_t
uint8_t
Definition: audio_convert.c:194
AV_SAMPLE_FMT_S16
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition: samplefmt.h:61
av_samples_get_buffer_size
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)
Get the required buffer size for the given audio parameters.
Definition: samplefmt.c:119
audiogen
static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt, int channels, int sample_rate, int nb_samples)
Definition: avresample.c:82
ret
ret
Definition: filter_design.txt:187
av_get_packed_sample_fmt
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition: samplefmt.c:75
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:70
av_clip_uint8
#define av_clip_uint8
Definition: common.h:128
mem.h
llrint
#define llrint(x)
Definition: libm.h:394
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AV_SAMPLE_FMT_DBL
@ AV_SAMPLE_FMT_DBL
double
Definition: samplefmt.h:64
avstring.h
AV_SAMPLE_FMT_S32
@ AV_SAMPLE_FMT_S32
signed 32 bits
Definition: samplefmt.h:62
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:63