swresample_test.c 9.34 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
 *
 * This file is part of libswresample
 *
 * libswresample is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * libswresample is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libswresample; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/audioconvert.h"
#include "swresample.h"
#undef fprintf

#define SAMPLES 1000

#define ASSERT_LEVEL 2

31 32 33 34 35 36 37 38 39 40
static double get(const uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f){
    const uint8_t *p;
    if(f>=0x100){
        f&=0xFF;
        p= a[ch];
    }else{
        p= a[0];
        index= ch + index*ch_count;
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
41 42 43 44 45 46 47 48 49 50
    switch(f){
    case AV_SAMPLE_FMT_U8 : return ((const uint8_t*)p)[index]/255.0*2-1.0;
    case AV_SAMPLE_FMT_S16: return ((const int16_t*)p)[index]/32767.0;
    case AV_SAMPLE_FMT_S32: return ((const int32_t*)p)[index]/2147483647.0;
    case AV_SAMPLE_FMT_FLT: return ((const float  *)p)[index];
    case AV_SAMPLE_FMT_DBL: return ((const double *)p)[index];
    default: av_assert2(0);
    }
}

51 52 53 54 55 56 57 58 59
static void  set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v){
    uint8_t *p;
    if(f>=0x100){
        f&=0xFF;
        p= a[ch];
    }else{
        p= a[0];
        index= ch + index*ch_count;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    switch(f){
    case AV_SAMPLE_FMT_U8 : ((uint8_t*)p)[index]= (v+1.0)*255.0/2; break;
    case AV_SAMPLE_FMT_S16: ((int16_t*)p)[index]= v*32767;         break;
    case AV_SAMPLE_FMT_S32: ((int32_t*)p)[index]= v*2147483647;    break;
    case AV_SAMPLE_FMT_FLT: ((float  *)p)[index]= v;               break;
    case AV_SAMPLE_FMT_DBL: ((double *)p)[index]= v;               break;
    default: av_assert2(0);
    }
}

uint64_t layouts[]={
AV_CH_LAYOUT_MONO                    ,
AV_CH_LAYOUT_STEREO                  ,
AV_CH_LAYOUT_2_1                     ,
AV_CH_LAYOUT_SURROUND                ,
AV_CH_LAYOUT_4POINT0                 ,
AV_CH_LAYOUT_2_2                     ,
AV_CH_LAYOUT_QUAD                    ,
AV_CH_LAYOUT_5POINT0                 ,
AV_CH_LAYOUT_5POINT1                 ,
AV_CH_LAYOUT_5POINT0_BACK            ,
AV_CH_LAYOUT_5POINT1_BACK            ,
AV_CH_LAYOUT_7POINT0                 ,
AV_CH_LAYOUT_7POINT1                 ,
AV_CH_LAYOUT_7POINT1_WIDE            ,
0
};

88 89 90 91 92 93 94 95 96 97 98 99 100
static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){
    if(format >= 0x100){
        int i;
        int plane_size= av_get_bytes_per_sample(format&0xFF)*samples;
        format&=0xFF;
        for(i=0; i<SWR_CH_MAX; i++){
            out[i]= in + i*plane_size;
        }
    }else{
        out[0]= in;
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
101
int main(int argc, char **argv){
102
    int in_sample_rate, out_sample_rate, ch ,i, in_ch_layout_index, out_ch_layout_index, osr, flush_count;
Michael Niedermayer's avatar
Michael Niedermayer committed
103 104 105 106 107 108
    uint64_t in_ch_layout, out_ch_layout;
    enum AVSampleFormat in_sample_fmt, out_sample_fmt;
    int sample_rates[]={8000,11025,16000,22050,32000};
    uint8_t array_in[SAMPLES*8*8];
    uint8_t array_mid[SAMPLES*8*8*3];
    uint8_t array_out[SAMPLES*8*8+100];
109 110 111 112 113
    uint8_t *ain[SWR_CH_MAX];
    uint8_t *aout[SWR_CH_MAX];
    uint8_t *amid[SWR_CH_MAX];
    int planar_in=256, planar_out=256;

Michael Niedermayer's avatar
Michael Niedermayer committed
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    struct SwrContext * forw_ctx= NULL;
    struct SwrContext *backw_ctx= NULL;

    in_sample_rate=16000;
    for(osr=0; osr<5; osr++){
        out_sample_rate= sample_rates[osr];
        for(in_sample_fmt= AV_SAMPLE_FMT_U8; in_sample_fmt<=AV_SAMPLE_FMT_DBL; in_sample_fmt++){
            for(out_sample_fmt= AV_SAMPLE_FMT_U8; out_sample_fmt<=AV_SAMPLE_FMT_DBL; out_sample_fmt++){
                for(in_ch_layout_index=0; layouts[in_ch_layout_index]; in_ch_layout_index++){
                    in_ch_layout= layouts[in_ch_layout_index];
                    int in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);
                    for(out_ch_layout_index=0; layouts[out_ch_layout_index]; out_ch_layout_index++){
                        int out_count, mid_count;
                        out_ch_layout= layouts[out_ch_layout_index];
                        int out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);
                        fprintf(stderr, "ch %d->%d, rate:%5d->%5d, fmt:%s->%s",
                               in_ch_count, out_ch_count,
                               in_sample_rate, out_sample_rate,
                               av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
133
                        forw_ctx  = swr_alloc2(forw_ctx, out_ch_layout, out_sample_fmt+planar_out, out_sample_rate,
134 135 136 137 138
                                                          in_ch_layout,  in_sample_fmt+planar_in ,  in_sample_rate,
                                                          NULL, 0, 0);
                        backw_ctx = swr_alloc2(backw_ctx,in_ch_layout,  in_sample_fmt,             in_sample_rate,
                                                        out_ch_layout, out_sample_fmt+planar_out, out_sample_rate,
                                                        NULL, 0, 0);
Michael Niedermayer's avatar
Michael Niedermayer committed
139 140 141 142 143 144 145 146 147
                        if(swr_init( forw_ctx) < 0)
                            fprintf(stderr, "swr_init(->) failed\n");
                        if(swr_init(backw_ctx) < 0)
                            fprintf(stderr, "swr_init(<-) failed\n");
                        if(!forw_ctx)
                            fprintf(stderr, "Failed to init forw_cts\n");
                        if(!backw_ctx)
                            fprintf(stderr, "Failed to init backw_ctx\n");
                               //FIXME test planar
148 149 150
                        setup_array(ain , array_in ,  in_sample_fmt+planar_in ,   SAMPLES);
                        setup_array(amid, array_mid, out_sample_fmt+planar_out, 3*SAMPLES);
                        setup_array(aout, array_out,  in_sample_fmt           ,   SAMPLES);
Michael Niedermayer's avatar
Michael Niedermayer committed
151 152
                        for(ch=0; ch<in_ch_count; ch++){
                            for(i=0; i<SAMPLES; i++)
153
                                set(ain, ch, i, in_ch_count, in_sample_fmt+planar_in, sin(i*i*3/SAMPLES));
Michael Niedermayer's avatar
Michael Niedermayer committed
154
                        }
155 156 157
                        mid_count= swr_convert(forw_ctx, amid, 3*SAMPLES, ain, SAMPLES);
                        out_count= swr_convert(backw_ctx,aout, SAMPLES, amid, mid_count);

Michael Niedermayer's avatar
Michael Niedermayer committed
158 159 160 161 162 163 164
                        for(ch=0; ch<in_ch_count; ch++){
                            double sse, x, maxdiff=0;
                            double sum_a= 0;
                            double sum_b= 0;
                            double sum_aa= 0;
                            double sum_bb= 0;
                            double sum_ab= 0;
165
                            for(i=0; i<out_count; i++){
166 167
                                double a= get(ain , ch, i, in_ch_count, in_sample_fmt+planar_in);
                                double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
Michael Niedermayer's avatar
Michael Niedermayer committed
168 169 170 171 172 173 174 175 176 177
                                sum_a += a;
                                sum_b += b;
                                sum_aa+= a*a;
                                sum_bb+= b*b;
                                sum_ab+= a*b;
                                maxdiff= FFMAX(maxdiff, FFABS(a-b));
                            }
                            x = sum_ab/sum_bb;
                            sse= sum_aa + sum_bb*x*x - 2*x*sum_ab;

178
                            fprintf(stderr, "[%f %f %f] len:%5d\n", sqrt(sse/out_count), x, maxdiff, out_count);
Michael Niedermayer's avatar
Michael Niedermayer committed
179
                        }
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

                        flush_count=swr_convert(backw_ctx,aout, SAMPLES, 0, 0);
                        if(flush_count){
                            for(ch=0; ch<in_ch_count; ch++){
                                double sse, x, maxdiff=0;
                                double sum_a= 0;
                                double sum_b= 0;
                                double sum_aa= 0;
                                double sum_bb= 0;
                                double sum_ab= 0;
                                for(i=0; i<flush_count; i++){
                                    double a= get(ain , ch, i+out_count, in_ch_count, in_sample_fmt+planar_in);
                                    double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
                                    sum_a += a;
                                    sum_b += b;
                                    sum_aa+= a*a;
                                    sum_bb+= b*b;
                                    sum_ab+= a*b;
                                    maxdiff= FFMAX(maxdiff, FFABS(a-b));
                                }
                                x = sum_ab/sum_bb;
                                sse= sum_aa + sum_bb*x*x - 2*x*sum_ab;

                                fprintf(stderr, "[%f %f %f] len:%5d\n", sqrt(sse/flush_count), x, maxdiff, flush_count);
                            }
                        }


Michael Niedermayer's avatar
Michael Niedermayer committed
208 209 210 211 212 213 214 215 216
                        fprintf(stderr, "\n");
                    }
                }
            }
        }
    }

    return 0;
}