Subversion Repositories Kolibri OS

Rev

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

  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.  
  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))
  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.  
  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.  
  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.