Browse code

buildsys: fix rules for swresample-test

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 63b1c08073adefb93c9fe8e3a6fd9c1b99772b7e)

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2012/06/06 00:06:19
Showing 3 changed files
... ...
@@ -7,4 +7,4 @@ HEADERS = swresample.h
7 7
 
8 8
 OBJS = swresample.o audioconvert.o resample.o rematrix.o dither.o
9 9
 
10
-TESTPROGS = swresample_test
10
+TESTPROGS = swresample
11 11
new file mode 100644
... ...
@@ -0,0 +1,410 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ * Copyright (c) 2002 Fabrice Bellard
3
+ *
4
+ * This file is part of libswresample
5
+ *
6
+ * libswresample is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * libswresample 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 General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with libswresample; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "libavutil/avassert.h"
22
+#include "libavutil/common.h"
23
+#include "libavutil/audioconvert.h"
24
+#include "libavutil/opt.h"
25
+#include "swresample.h"
26
+
27
+#undef time
28
+#include "time.h"
29
+#undef fprintf
30
+
31
+#define SAMPLES 1000
32
+
33
+#define ASSERT_LEVEL 2
34
+
35
+static double get(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f){
36
+    const uint8_t *p;
37
+    if(av_sample_fmt_is_planar(f)){
38
+        f= av_get_alt_sample_fmt(f, 0);
39
+        p= a[ch];
40
+    }else{
41
+        p= a[0];
42
+        index= ch + index*ch_count;
43
+    }
44
+
45
+    switch(f){
46
+    case AV_SAMPLE_FMT_U8 : return ((const uint8_t*)p)[index]/127.0-1.0;
47
+    case AV_SAMPLE_FMT_S16: return ((const int16_t*)p)[index]/32767.0;
48
+    case AV_SAMPLE_FMT_S32: return ((const int32_t*)p)[index]/2147483647.0;
49
+    case AV_SAMPLE_FMT_FLT: return ((const float  *)p)[index];
50
+    case AV_SAMPLE_FMT_DBL: return ((const double *)p)[index];
51
+    default: av_assert0(0);
52
+    }
53
+}
54
+
55
+static void  set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v){
56
+    uint8_t *p;
57
+    if(av_sample_fmt_is_planar(f)){
58
+        f= av_get_alt_sample_fmt(f, 0);
59
+        p= a[ch];
60
+    }else{
61
+        p= a[0];
62
+        index= ch + index*ch_count;
63
+    }
64
+    switch(f){
65
+    case AV_SAMPLE_FMT_U8 : ((uint8_t*)p)[index]= av_clip_uint8 (lrint((v+1.0)*127));     break;
66
+    case AV_SAMPLE_FMT_S16: ((int16_t*)p)[index]= av_clip_int16 (lrint(v*32767));         break;
67
+    case AV_SAMPLE_FMT_S32: ((int32_t*)p)[index]= av_clipl_int32(lrint(v*2147483647));    break;
68
+    case AV_SAMPLE_FMT_FLT: ((float  *)p)[index]= v;                                      break;
69
+    case AV_SAMPLE_FMT_DBL: ((double *)p)[index]= v;                                      break;
70
+    default: av_assert2(0);
71
+    }
72
+}
73
+
74
+static void shift(uint8_t *a[], int index, int ch_count, enum AVSampleFormat f){
75
+    int ch;
76
+
77
+    if(av_sample_fmt_is_planar(f)){
78
+        f= av_get_alt_sample_fmt(f, 0);
79
+        for(ch= 0; ch<ch_count; ch++)
80
+            a[ch] += index*av_get_bytes_per_sample(f);
81
+    }else{
82
+        a[0] += index*ch_count*av_get_bytes_per_sample(f);
83
+    }
84
+}
85
+
86
+static const enum AVSampleFormat formats[] = {
87
+    AV_SAMPLE_FMT_S16,
88
+    AV_SAMPLE_FMT_FLTP,
89
+    AV_SAMPLE_FMT_S16P,
90
+    AV_SAMPLE_FMT_FLT,
91
+    AV_SAMPLE_FMT_S32P,
92
+    AV_SAMPLE_FMT_S32,
93
+    AV_SAMPLE_FMT_U8P,
94
+    AV_SAMPLE_FMT_U8,
95
+    AV_SAMPLE_FMT_DBLP,
96
+    AV_SAMPLE_FMT_DBL,
97
+};
98
+
99
+static const int rates[] = {
100
+    8000,
101
+    11025,
102
+    16000,
103
+    22050,
104
+    32000,
105
+    48000,
106
+};
107
+
108
+uint64_t layouts[]={
109
+    AV_CH_LAYOUT_MONO                    ,
110
+    AV_CH_LAYOUT_STEREO                  ,
111
+    AV_CH_LAYOUT_2_1                     ,
112
+    AV_CH_LAYOUT_SURROUND                ,
113
+    AV_CH_LAYOUT_4POINT0                 ,
114
+    AV_CH_LAYOUT_2_2                     ,
115
+    AV_CH_LAYOUT_QUAD                    ,
116
+    AV_CH_LAYOUT_5POINT0                 ,
117
+    AV_CH_LAYOUT_5POINT1                 ,
118
+    AV_CH_LAYOUT_5POINT0_BACK            ,
119
+    AV_CH_LAYOUT_5POINT1_BACK            ,
120
+    AV_CH_LAYOUT_7POINT0                 ,
121
+    AV_CH_LAYOUT_7POINT1                 ,
122
+    AV_CH_LAYOUT_7POINT1_WIDE            ,
123
+};
124
+
125
+static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){
126
+    if(av_sample_fmt_is_planar(format)){
127
+        int i;
128
+        int plane_size= av_get_bytes_per_sample(format&0xFF)*samples;
129
+        format&=0xFF;
130
+        for(i=0; i<SWR_CH_MAX; i++){
131
+            out[i]= in + i*plane_size;
132
+        }
133
+    }else{
134
+        out[0]= in;
135
+    }
136
+}
137
+
138
+static int cmp(const int *a, const int *b){
139
+    return *a - *b;
140
+}
141
+
142
+static void audiogen(void *data, enum AVSampleFormat sample_fmt,
143
+                     int channels, int sample_rate, int nb_samples)
144
+{
145
+    int i, ch, k;
146
+    double v, f, a, ampa;
147
+    double tabf1[SWR_CH_MAX];
148
+    double tabf2[SWR_CH_MAX];
149
+    double taba[SWR_CH_MAX];
150
+    unsigned static rnd;
151
+
152
+#define PUT_SAMPLE set(data, ch, k, channels, sample_fmt, v);
153
+#define uint_rand(x) (x = x * 1664525 + 1013904223)
154
+#define dbl_rand(x) (uint_rand(x)*2.0 / (double)UINT_MAX - 1)
155
+    k = 0;
156
+
157
+    /* 1 second of single freq sinus at 1000 Hz */
158
+    a = 0;
159
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
160
+        v = sin(a) * 0.30;
161
+        for (ch = 0; ch < channels; ch++)
162
+            PUT_SAMPLE
163
+        a += M_PI * 1000.0 * 2.0 / sample_rate;
164
+    }
165
+
166
+    /* 1 second of varing frequency between 100 and 10000 Hz */
167
+    a = 0;
168
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
169
+        v = sin(a) * 0.30;
170
+        for (ch = 0; ch < channels; ch++)
171
+            PUT_SAMPLE
172
+        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
173
+        a += M_PI * f * 2.0 / sample_rate;
174
+    }
175
+
176
+    /* 0.5 second of low amplitude white noise */
177
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
178
+        v = dbl_rand(rnd) * 0.30;
179
+        for (ch = 0; ch < channels; ch++)
180
+            PUT_SAMPLE
181
+    }
182
+
183
+    /* 0.5 second of high amplitude white noise */
184
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
185
+        v = dbl_rand(rnd);
186
+        for (ch = 0; ch < channels; ch++)
187
+            PUT_SAMPLE
188
+    }
189
+
190
+    /* 1 second of unrelated ramps for each channel */
191
+    for (ch = 0; ch < channels; ch++) {
192
+        taba[ch]  = 0;
193
+        tabf1[ch] = 100 + uint_rand(rnd) % 5000;
194
+        tabf2[ch] = 100 + uint_rand(rnd) % 5000;
195
+    }
196
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
197
+        for (ch = 0; ch < channels; ch++) {
198
+            v = sin(taba[ch]) * 0.30;
199
+            PUT_SAMPLE
200
+            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
201
+            taba[ch] += M_PI * f * 2.0 / sample_rate;
202
+        }
203
+    }
204
+
205
+    /* 2 seconds of 500 Hz with varying volume */
206
+    a    = 0;
207
+    ampa = 0;
208
+    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
209
+        for (ch = 0; ch < channels; ch++) {
210
+            double amp = (1.0 + sin(ampa)) * 0.15;
211
+            if (ch & 1)
212
+                amp = 0.30 - amp;
213
+            v = sin(a) * amp;
214
+            PUT_SAMPLE
215
+            a    += M_PI * 500.0 * 2.0 / sample_rate;
216
+            ampa += M_PI *  2.0 / sample_rate;
217
+        }
218
+    }
219
+}
220
+
221
+int main(int argc, char **argv){
222
+    int in_sample_rate, out_sample_rate, ch ,i, flush_count;
223
+    uint64_t in_ch_layout, out_ch_layout;
224
+    enum AVSampleFormat in_sample_fmt, out_sample_fmt;
225
+    uint8_t array_in[SAMPLES*8*8];
226
+    uint8_t array_mid[SAMPLES*8*8*3];
227
+    uint8_t array_out[SAMPLES*8*8+100];
228
+    uint8_t *ain[SWR_CH_MAX];
229
+    uint8_t *aout[SWR_CH_MAX];
230
+    uint8_t *amid[SWR_CH_MAX];
231
+    int flush_i=0;
232
+    int mode;
233
+    int max_tests = FF_ARRAY_ELEMS(rates) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats);
234
+    int num_tests = 10000;
235
+    uint32_t seed = 0;
236
+    uint32_t rand_seed = 0;
237
+    int remaining_tests[max_tests];
238
+    int test;
239
+    int specific_test= -1;
240
+
241
+    struct SwrContext * forw_ctx= NULL;
242
+    struct SwrContext *backw_ctx= NULL;
243
+
244
+    if (argc > 1) {
245
+        if (!strcmp(argv[1], "-h")) {
246
+            av_log(NULL, AV_LOG_INFO, "Usage: swresample-test [<num_tests>[ <test>]]  \n"
247
+                   "num_tests           Default is %d\n", num_tests);
248
+            return 0;
249
+        }
250
+        num_tests = strtol(argv[1], NULL, 0);
251
+        if(num_tests < 0) {
252
+            num_tests = -num_tests;
253
+            rand_seed = time(0);
254
+        }
255
+        if(num_tests<= 0 || num_tests>max_tests)
256
+            num_tests = max_tests;
257
+        if(argc > 2) {
258
+            specific_test = strtol(argv[1], NULL, 0);
259
+        }
260
+    }
261
+
262
+    for(i=0; i<max_tests; i++)
263
+        remaining_tests[i] = i;
264
+
265
+    for(test=0; test<num_tests; test++){
266
+        unsigned r;
267
+        uint_rand(seed);
268
+        r = (seed * (uint64_t)(max_tests - test)) >>32;
269
+        FFSWAP(int, remaining_tests[r], remaining_tests[max_tests - test - 1]);
270
+    }
271
+    qsort(remaining_tests + max_tests - num_tests, num_tests, sizeof(remaining_tests[0]), (void*)cmp);
272
+    in_sample_rate=16000;
273
+    for(test=0; test<num_tests; test++){
274
+        char  in_layout_string[256];
275
+        char out_layout_string[256];
276
+        unsigned vector= remaining_tests[max_tests - test - 1];
277
+        int in_ch_count;
278
+        int out_count, mid_count, out_ch_count;
279
+
280
+        in_ch_layout    = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
281
+        out_ch_layout   = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
282
+        in_sample_fmt   = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
283
+        out_sample_fmt  = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
284
+        out_sample_rate = rates  [vector % FF_ARRAY_ELEMS(rates  )]; vector /= FF_ARRAY_ELEMS(rates);
285
+        av_assert0(!vector);
286
+
287
+        if(specific_test == 0){
288
+            if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout)
289
+                continue;
290
+        }
291
+
292
+        in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);
293
+        out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);
294
+        av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string),  in_ch_count,  in_ch_layout);
295
+        av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout);
296
+        fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n",
297
+                in_layout_string, out_layout_string,
298
+                in_sample_rate, out_sample_rate,
299
+                av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
300
+        forw_ctx  = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt,  out_sample_rate,
301
+                                                    in_ch_layout,  in_sample_fmt,  in_sample_rate,
302
+                                        0, 0);
303
+        backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout,  in_sample_fmt,             in_sample_rate,
304
+                                                    out_ch_layout, out_sample_fmt, out_sample_rate,
305
+                                        0, 0);
306
+        if(swr_init( forw_ctx) < 0)
307
+            fprintf(stderr, "swr_init(->) failed\n");
308
+        if(swr_init(backw_ctx) < 0)
309
+            fprintf(stderr, "swr_init(<-) failed\n");
310
+        if(!forw_ctx)
311
+            fprintf(stderr, "Failed to init forw_cts\n");
312
+        if(!backw_ctx)
313
+            fprintf(stderr, "Failed to init backw_ctx\n");
314
+                //FIXME test planar
315
+        setup_array(ain , array_in ,  in_sample_fmt,   SAMPLES);
316
+        setup_array(amid, array_mid, out_sample_fmt, 3*SAMPLES);
317
+        setup_array(aout, array_out,  in_sample_fmt           ,   SAMPLES);
318
+#if 0
319
+        for(ch=0; ch<in_ch_count; ch++){
320
+            for(i=0; i<SAMPLES; i++)
321
+                set(ain, ch, i, in_ch_count, in_sample_fmt, sin(i*i*3/SAMPLES));
322
+        }
323
+#else
324
+        audiogen(ain, in_sample_fmt, in_ch_count, SAMPLES/6+1, SAMPLES);
325
+#endif
326
+        mode = uint_rand(rand_seed) % 3;
327
+        if(mode==0 /*|| out_sample_rate == in_sample_rate*/) {
328
+            mid_count= swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain, SAMPLES);
329
+        } else if(mode==1){
330
+            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain, SAMPLES);
331
+            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
332
+        } else {
333
+            int tmp_count;
334
+            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain,       1);
335
+            av_assert0(mid_count==0);
336
+            shift(ain,  1, in_ch_count, in_sample_fmt);
337
+            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
338
+            shift(amid,  mid_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
339
+            mid_count+=swr_convert(forw_ctx, amid,         2, (const uint8_t **)ain,       2);
340
+            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
341
+            shift(ain,  2, in_ch_count, in_sample_fmt);
342
+            mid_count+=swr_convert(forw_ctx, amid,         1, (const uint8_t **)ain, SAMPLES-3);
343
+            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
344
+            shift(ain, -3, in_ch_count, in_sample_fmt);
345
+            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
346
+            shift(amid,  -tmp_count, out_ch_count, out_sample_fmt);
347
+        }
348
+        out_count= swr_convert(backw_ctx,aout, SAMPLES, (const uint8_t **)amid, mid_count);
349
+
350
+        for(ch=0; ch<in_ch_count; ch++){
351
+            double sse, maxdiff=0;
352
+            double sum_a= 0;
353
+            double sum_b= 0;
354
+            double sum_aa= 0;
355
+            double sum_bb= 0;
356
+            double sum_ab= 0;
357
+            for(i=0; i<out_count; i++){
358
+                double a= get(ain , ch, i, in_ch_count, in_sample_fmt);
359
+                double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
360
+                sum_a += a;
361
+                sum_b += b;
362
+                sum_aa+= a*a;
363
+                sum_bb+= b*b;
364
+                sum_ab+= a*b;
365
+                maxdiff= FFMAX(maxdiff, FFABS(a-b));
366
+            }
367
+            sse= sum_aa + sum_bb - 2*sum_ab;
368
+            if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
369
+
370
+            fprintf(stderr, "[e:%f c:%f max:%f] len:%5d\n", sqrt(sse/out_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, out_count);
371
+        }
372
+
373
+        flush_i++;
374
+        flush_i%=21;
375
+        flush_count = swr_convert(backw_ctx,aout, flush_i, 0, 0);
376
+        shift(aout,  flush_i, in_ch_count, in_sample_fmt);
377
+        flush_count+= swr_convert(backw_ctx,aout, SAMPLES-flush_i, 0, 0);
378
+        shift(aout, -flush_i, in_ch_count, in_sample_fmt);
379
+        if(flush_count){
380
+            for(ch=0; ch<in_ch_count; ch++){
381
+                double sse, maxdiff=0;
382
+                double sum_a= 0;
383
+                double sum_b= 0;
384
+                double sum_aa= 0;
385
+                double sum_bb= 0;
386
+                double sum_ab= 0;
387
+                for(i=0; i<flush_count; i++){
388
+                    double a= get(ain , ch, i+out_count, in_ch_count, in_sample_fmt);
389
+                    double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
390
+                    sum_a += a;
391
+                    sum_b += b;
392
+                    sum_aa+= a*a;
393
+                    sum_bb+= b*b;
394
+                    sum_ab+= a*b;
395
+                    maxdiff= FFMAX(maxdiff, FFABS(a-b));
396
+                }
397
+                sse= sum_aa + sum_bb - 2*sum_ab;
398
+                if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
399
+
400
+                fprintf(stderr, "[e:%f c:%f max:%f] len:%5d F:%3d\n", sqrt(sse/flush_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, flush_count, flush_i);
401
+            }
402
+        }
403
+
404
+
405
+        fprintf(stderr, "\n");
406
+    }
407
+
408
+    return 0;
409
+}
0 410
deleted file mode 100644
... ...
@@ -1,410 +0,0 @@
1
-/*
2
- * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
3
- * Copyright (c) 2002 Fabrice Bellard
4
- *
5
- * This file is part of libswresample
6
- *
7
- * libswresample is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * libswresample 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
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with libswresample; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
- */
21
-
22
-#include "libavutil/avassert.h"
23
-#include "libavutil/common.h"
24
-#include "libavutil/audioconvert.h"
25
-#include "libavutil/opt.h"
26
-#include "swresample.h"
27
-
28
-#undef time
29
-#include "time.h"
30
-#undef fprintf
31
-
32
-#define SAMPLES 1000
33
-
34
-#define ASSERT_LEVEL 2
35
-
36
-static double get(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f){
37
-    const uint8_t *p;
38
-    if(av_sample_fmt_is_planar(f)){
39
-        f= av_get_alt_sample_fmt(f, 0);
40
-        p= a[ch];
41
-    }else{
42
-        p= a[0];
43
-        index= ch + index*ch_count;
44
-    }
45
-
46
-    switch(f){
47
-    case AV_SAMPLE_FMT_U8 : return ((const uint8_t*)p)[index]/127.0-1.0;
48
-    case AV_SAMPLE_FMT_S16: return ((const int16_t*)p)[index]/32767.0;
49
-    case AV_SAMPLE_FMT_S32: return ((const int32_t*)p)[index]/2147483647.0;
50
-    case AV_SAMPLE_FMT_FLT: return ((const float  *)p)[index];
51
-    case AV_SAMPLE_FMT_DBL: return ((const double *)p)[index];
52
-    default: av_assert0(0);
53
-    }
54
-}
55
-
56
-static void  set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v){
57
-    uint8_t *p;
58
-    if(av_sample_fmt_is_planar(f)){
59
-        f= av_get_alt_sample_fmt(f, 0);
60
-        p= a[ch];
61
-    }else{
62
-        p= a[0];
63
-        index= ch + index*ch_count;
64
-    }
65
-    switch(f){
66
-    case AV_SAMPLE_FMT_U8 : ((uint8_t*)p)[index]= av_clip_uint8 (lrint((v+1.0)*127));     break;
67
-    case AV_SAMPLE_FMT_S16: ((int16_t*)p)[index]= av_clip_int16 (lrint(v*32767));         break;
68
-    case AV_SAMPLE_FMT_S32: ((int32_t*)p)[index]= av_clipl_int32(lrint(v*2147483647));    break;
69
-    case AV_SAMPLE_FMT_FLT: ((float  *)p)[index]= v;                                      break;
70
-    case AV_SAMPLE_FMT_DBL: ((double *)p)[index]= v;                                      break;
71
-    default: av_assert2(0);
72
-    }
73
-}
74
-
75
-static void shift(uint8_t *a[], int index, int ch_count, enum AVSampleFormat f){
76
-    int ch;
77
-
78
-    if(av_sample_fmt_is_planar(f)){
79
-        f= av_get_alt_sample_fmt(f, 0);
80
-        for(ch= 0; ch<ch_count; ch++)
81
-            a[ch] += index*av_get_bytes_per_sample(f);
82
-    }else{
83
-        a[0] += index*ch_count*av_get_bytes_per_sample(f);
84
-    }
85
-}
86
-
87
-static const enum AVSampleFormat formats[] = {
88
-    AV_SAMPLE_FMT_S16,
89
-    AV_SAMPLE_FMT_FLTP,
90
-    AV_SAMPLE_FMT_S16P,
91
-    AV_SAMPLE_FMT_FLT,
92
-    AV_SAMPLE_FMT_S32P,
93
-    AV_SAMPLE_FMT_S32,
94
-    AV_SAMPLE_FMT_U8P,
95
-    AV_SAMPLE_FMT_U8,
96
-    AV_SAMPLE_FMT_DBLP,
97
-    AV_SAMPLE_FMT_DBL,
98
-};
99
-
100
-static const int rates[] = {
101
-    8000,
102
-    11025,
103
-    16000,
104
-    22050,
105
-    32000,
106
-    48000,
107
-};
108
-
109
-uint64_t layouts[]={
110
-    AV_CH_LAYOUT_MONO                    ,
111
-    AV_CH_LAYOUT_STEREO                  ,
112
-    AV_CH_LAYOUT_2_1                     ,
113
-    AV_CH_LAYOUT_SURROUND                ,
114
-    AV_CH_LAYOUT_4POINT0                 ,
115
-    AV_CH_LAYOUT_2_2                     ,
116
-    AV_CH_LAYOUT_QUAD                    ,
117
-    AV_CH_LAYOUT_5POINT0                 ,
118
-    AV_CH_LAYOUT_5POINT1                 ,
119
-    AV_CH_LAYOUT_5POINT0_BACK            ,
120
-    AV_CH_LAYOUT_5POINT1_BACK            ,
121
-    AV_CH_LAYOUT_7POINT0                 ,
122
-    AV_CH_LAYOUT_7POINT1                 ,
123
-    AV_CH_LAYOUT_7POINT1_WIDE            ,
124
-};
125
-
126
-static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){
127
-    if(av_sample_fmt_is_planar(format)){
128
-        int i;
129
-        int plane_size= av_get_bytes_per_sample(format&0xFF)*samples;
130
-        format&=0xFF;
131
-        for(i=0; i<SWR_CH_MAX; i++){
132
-            out[i]= in + i*plane_size;
133
-        }
134
-    }else{
135
-        out[0]= in;
136
-    }
137
-}
138
-
139
-static int cmp(const int *a, const int *b){
140
-    return *a - *b;
141
-}
142
-
143
-static void audiogen(void *data, enum AVSampleFormat sample_fmt,
144
-                     int channels, int sample_rate, int nb_samples)
145
-{
146
-    int i, ch, k;
147
-    double v, f, a, ampa;
148
-    double tabf1[SWR_CH_MAX];
149
-    double tabf2[SWR_CH_MAX];
150
-    double taba[SWR_CH_MAX];
151
-    unsigned static rnd;
152
-
153
-#define PUT_SAMPLE set(data, ch, k, channels, sample_fmt, v);
154
-#define uint_rand(x) (x = x * 1664525 + 1013904223)
155
-#define dbl_rand(x) (uint_rand(x)*2.0 / (double)UINT_MAX - 1)
156
-    k = 0;
157
-
158
-    /* 1 second of single freq sinus at 1000 Hz */
159
-    a = 0;
160
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
161
-        v = sin(a) * 0.30;
162
-        for (ch = 0; ch < channels; ch++)
163
-            PUT_SAMPLE
164
-        a += M_PI * 1000.0 * 2.0 / sample_rate;
165
-    }
166
-
167
-    /* 1 second of varing frequency between 100 and 10000 Hz */
168
-    a = 0;
169
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
170
-        v = sin(a) * 0.30;
171
-        for (ch = 0; ch < channels; ch++)
172
-            PUT_SAMPLE
173
-        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
174
-        a += M_PI * f * 2.0 / sample_rate;
175
-    }
176
-
177
-    /* 0.5 second of low amplitude white noise */
178
-    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
179
-        v = dbl_rand(rnd) * 0.30;
180
-        for (ch = 0; ch < channels; ch++)
181
-            PUT_SAMPLE
182
-    }
183
-
184
-    /* 0.5 second of high amplitude white noise */
185
-    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
186
-        v = dbl_rand(rnd);
187
-        for (ch = 0; ch < channels; ch++)
188
-            PUT_SAMPLE
189
-    }
190
-
191
-    /* 1 second of unrelated ramps for each channel */
192
-    for (ch = 0; ch < channels; ch++) {
193
-        taba[ch]  = 0;
194
-        tabf1[ch] = 100 + uint_rand(rnd) % 5000;
195
-        tabf2[ch] = 100 + uint_rand(rnd) % 5000;
196
-    }
197
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
198
-        for (ch = 0; ch < channels; ch++) {
199
-            v = sin(taba[ch]) * 0.30;
200
-            PUT_SAMPLE
201
-            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
202
-            taba[ch] += M_PI * f * 2.0 / sample_rate;
203
-        }
204
-    }
205
-
206
-    /* 2 seconds of 500 Hz with varying volume */
207
-    a    = 0;
208
-    ampa = 0;
209
-    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
210
-        for (ch = 0; ch < channels; ch++) {
211
-            double amp = (1.0 + sin(ampa)) * 0.15;
212
-            if (ch & 1)
213
-                amp = 0.30 - amp;
214
-            v = sin(a) * amp;
215
-            PUT_SAMPLE
216
-            a    += M_PI * 500.0 * 2.0 / sample_rate;
217
-            ampa += M_PI *  2.0 / sample_rate;
218
-        }
219
-    }
220
-}
221
-
222
-int main(int argc, char **argv){
223
-    int in_sample_rate, out_sample_rate, ch ,i, flush_count;
224
-    uint64_t in_ch_layout, out_ch_layout;
225
-    enum AVSampleFormat in_sample_fmt, out_sample_fmt;
226
-    uint8_t array_in[SAMPLES*8*8];
227
-    uint8_t array_mid[SAMPLES*8*8*3];
228
-    uint8_t array_out[SAMPLES*8*8+100];
229
-    uint8_t *ain[SWR_CH_MAX];
230
-    uint8_t *aout[SWR_CH_MAX];
231
-    uint8_t *amid[SWR_CH_MAX];
232
-    int flush_i=0;
233
-    int mode;
234
-    int max_tests = FF_ARRAY_ELEMS(rates) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats);
235
-    int num_tests = 10000;
236
-    uint32_t seed = 0;
237
-    uint32_t rand_seed = 0;
238
-    int remaining_tests[max_tests];
239
-    int test;
240
-    int specific_test= -1;
241
-
242
-    struct SwrContext * forw_ctx= NULL;
243
-    struct SwrContext *backw_ctx= NULL;
244
-
245
-    if (argc > 1) {
246
-        if (!strcmp(argv[1], "-h")) {
247
-            av_log(NULL, AV_LOG_INFO, "Usage: swresample-test [<num_tests>[ <test>]]  \n"
248
-                   "num_tests           Default is %d\n", num_tests);
249
-            return 0;
250
-        }
251
-        num_tests = strtol(argv[1], NULL, 0);
252
-        if(num_tests < 0) {
253
-            num_tests = -num_tests;
254
-            rand_seed = time(0);
255
-        }
256
-        if(num_tests<= 0 || num_tests>max_tests)
257
-            num_tests = max_tests;
258
-        if(argc > 2) {
259
-            specific_test = strtol(argv[1], NULL, 0);
260
-        }
261
-    }
262
-
263
-    for(i=0; i<max_tests; i++)
264
-        remaining_tests[i] = i;
265
-
266
-    for(test=0; test<num_tests; test++){
267
-        unsigned r;
268
-        uint_rand(seed);
269
-        r = (seed * (uint64_t)(max_tests - test)) >>32;
270
-        FFSWAP(int, remaining_tests[r], remaining_tests[max_tests - test - 1]);
271
-    }
272
-    qsort(remaining_tests + max_tests - num_tests, num_tests, sizeof(remaining_tests[0]), (void*)cmp);
273
-    in_sample_rate=16000;
274
-    for(test=0; test<num_tests; test++){
275
-        char  in_layout_string[256];
276
-        char out_layout_string[256];
277
-        unsigned vector= remaining_tests[max_tests - test - 1];
278
-        int in_ch_count;
279
-        int out_count, mid_count, out_ch_count;
280
-
281
-        in_ch_layout    = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
282
-        out_ch_layout   = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
283
-        in_sample_fmt   = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
284
-        out_sample_fmt  = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
285
-        out_sample_rate = rates  [vector % FF_ARRAY_ELEMS(rates  )]; vector /= FF_ARRAY_ELEMS(rates);
286
-        av_assert0(!vector);
287
-
288
-        if(specific_test == 0){
289
-            if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout)
290
-                continue;
291
-        }
292
-
293
-        in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);
294
-        out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);
295
-        av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string),  in_ch_count,  in_ch_layout);
296
-        av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout);
297
-        fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n",
298
-                in_layout_string, out_layout_string,
299
-                in_sample_rate, out_sample_rate,
300
-                av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
301
-        forw_ctx  = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt,  out_sample_rate,
302
-                                                    in_ch_layout,  in_sample_fmt,  in_sample_rate,
303
-                                        0, 0);
304
-        backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout,  in_sample_fmt,             in_sample_rate,
305
-                                                    out_ch_layout, out_sample_fmt, out_sample_rate,
306
-                                        0, 0);
307
-        if(swr_init( forw_ctx) < 0)
308
-            fprintf(stderr, "swr_init(->) failed\n");
309
-        if(swr_init(backw_ctx) < 0)
310
-            fprintf(stderr, "swr_init(<-) failed\n");
311
-        if(!forw_ctx)
312
-            fprintf(stderr, "Failed to init forw_cts\n");
313
-        if(!backw_ctx)
314
-            fprintf(stderr, "Failed to init backw_ctx\n");
315
-                //FIXME test planar
316
-        setup_array(ain , array_in ,  in_sample_fmt,   SAMPLES);
317
-        setup_array(amid, array_mid, out_sample_fmt, 3*SAMPLES);
318
-        setup_array(aout, array_out,  in_sample_fmt           ,   SAMPLES);
319
-#if 0
320
-        for(ch=0; ch<in_ch_count; ch++){
321
-            for(i=0; i<SAMPLES; i++)
322
-                set(ain, ch, i, in_ch_count, in_sample_fmt, sin(i*i*3/SAMPLES));
323
-        }
324
-#else
325
-        audiogen(ain, in_sample_fmt, in_ch_count, SAMPLES/6+1, SAMPLES);
326
-#endif
327
-        mode = uint_rand(rand_seed) % 3;
328
-        if(mode==0 /*|| out_sample_rate == in_sample_rate*/) {
329
-            mid_count= swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain, SAMPLES);
330
-        } else if(mode==1){
331
-            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain, SAMPLES);
332
-            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
333
-        } else {
334
-            int tmp_count;
335
-            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain,       1);
336
-            av_assert0(mid_count==0);
337
-            shift(ain,  1, in_ch_count, in_sample_fmt);
338
-            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
339
-            shift(amid,  mid_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
340
-            mid_count+=swr_convert(forw_ctx, amid,         2, (const uint8_t **)ain,       2);
341
-            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
342
-            shift(ain,  2, in_ch_count, in_sample_fmt);
343
-            mid_count+=swr_convert(forw_ctx, amid,         1, (const uint8_t **)ain, SAMPLES-3);
344
-            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
345
-            shift(ain, -3, in_ch_count, in_sample_fmt);
346
-            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
347
-            shift(amid,  -tmp_count, out_ch_count, out_sample_fmt);
348
-        }
349
-        out_count= swr_convert(backw_ctx,aout, SAMPLES, (const uint8_t **)amid, mid_count);
350
-
351
-        for(ch=0; ch<in_ch_count; ch++){
352
-            double sse, maxdiff=0;
353
-            double sum_a= 0;
354
-            double sum_b= 0;
355
-            double sum_aa= 0;
356
-            double sum_bb= 0;
357
-            double sum_ab= 0;
358
-            for(i=0; i<out_count; i++){
359
-                double a= get(ain , ch, i, in_ch_count, in_sample_fmt);
360
-                double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
361
-                sum_a += a;
362
-                sum_b += b;
363
-                sum_aa+= a*a;
364
-                sum_bb+= b*b;
365
-                sum_ab+= a*b;
366
-                maxdiff= FFMAX(maxdiff, FFABS(a-b));
367
-            }
368
-            sse= sum_aa + sum_bb - 2*sum_ab;
369
-            if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
370
-
371
-            fprintf(stderr, "[e:%f c:%f max:%f] len:%5d\n", sqrt(sse/out_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, out_count);
372
-        }
373
-
374
-        flush_i++;
375
-        flush_i%=21;
376
-        flush_count = swr_convert(backw_ctx,aout, flush_i, 0, 0);
377
-        shift(aout,  flush_i, in_ch_count, in_sample_fmt);
378
-        flush_count+= swr_convert(backw_ctx,aout, SAMPLES-flush_i, 0, 0);
379
-        shift(aout, -flush_i, in_ch_count, in_sample_fmt);
380
-        if(flush_count){
381
-            for(ch=0; ch<in_ch_count; ch++){
382
-                double sse, maxdiff=0;
383
-                double sum_a= 0;
384
-                double sum_b= 0;
385
-                double sum_aa= 0;
386
-                double sum_bb= 0;
387
-                double sum_ab= 0;
388
-                for(i=0; i<flush_count; i++){
389
-                    double a= get(ain , ch, i+out_count, in_ch_count, in_sample_fmt);
390
-                    double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
391
-                    sum_a += a;
392
-                    sum_b += b;
393
-                    sum_aa+= a*a;
394
-                    sum_bb+= b*b;
395
-                    sum_ab+= a*b;
396
-                    maxdiff= FFMAX(maxdiff, FFABS(a-b));
397
-                }
398
-                sse= sum_aa + sum_bb - 2*sum_ab;
399
-                if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
400
-
401
-                fprintf(stderr, "[e:%f c:%f max:%f] len:%5d F:%3d\n", sqrt(sse/flush_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, flush_count, flush_i);
402
-            }
403
-        }
404
-
405
-
406
-        fprintf(stderr, "\n");
407
-    }
408
-
409
-    return 0;
410
-}