resample.c 11.6 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
Diego Biurrun's avatar
Diego Biurrun committed
2
 * samplerate conversion for both audio and video
3
 * Copyright (c) 2000 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
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
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
21 22

/**
23
 * @file
Diego Biurrun's avatar
Diego Biurrun committed
24
 * samplerate conversion for both audio and video
Michael Niedermayer's avatar
Michael Niedermayer committed
25 26
 */

Fabrice Bellard's avatar
Fabrice Bellard committed
27
#include "avcodec.h"
28
#include "audioconvert.h"
29
#include "libavutil/opt.h"
30
#include "libavutil/samplefmt.h"
31

32
struct AVResampleContext;
Fabrice Bellard's avatar
Fabrice Bellard committed
33

34 35 36 37 38 39
static const char *context_to_name(void *ptr)
{
    return "audioresample";
}

static const AVOption options[] = {{NULL}};
40
static const AVClass audioresample_context_class = { "ReSampleContext", context_to_name, options, LIBAVUTIL_VERSION_INT };
41

Fabrice Bellard's avatar
Fabrice Bellard committed
42
struct ReSampleContext {
43 44 45
    struct AVResampleContext *resample_context;
    short *temp[2];
    int temp_len;
Fabrice Bellard's avatar
Fabrice Bellard committed
46 47 48
    float ratio;
    /* channel convert */
    int input_channels, output_channels, filter_channels;
49
    AVAudioConvert *convert_ctx[2];
50
    enum AVSampleFormat sample_fmt[2]; ///< input and output sample format
51 52 53
    unsigned sample_size[2];         ///< size of one sample in sample_fmt
    short *buffer[2];                ///< buffers used for conversion to S16
    unsigned buffer_size[2];         ///< sizes of allocated buffers
Fabrice Bellard's avatar
Fabrice Bellard committed
54 55 56 57 58 59 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
};

/* n1: number of samples */
static void stereo_to_mono(short *output, short *input, int n1)
{
    short *p, *q;
    int n = n1;

    p = input;
    q = output;
    while (n >= 4) {
        q[0] = (p[0] + p[1]) >> 1;
        q[1] = (p[2] + p[3]) >> 1;
        q[2] = (p[4] + p[5]) >> 1;
        q[3] = (p[6] + p[7]) >> 1;
        q += 4;
        p += 8;
        n -= 4;
    }
    while (n > 0) {
        q[0] = (p[0] + p[1]) >> 1;
        q++;
        p += 2;
        n--;
    }
}

/* n1: number of samples */
static void mono_to_stereo(short *output, short *input, int n1)
{
    short *p, *q;
    int n = n1;
    int v;

    p = input;
    q = output;
    while (n >= 4) {
        v = p[0]; q[0] = v; q[1] = v;
        v = p[1]; q[2] = v; q[3] = v;
        v = p[2]; q[4] = v; q[5] = v;
        v = p[3]; q[6] = v; q[7] = v;
        q += 8;
        p += 4;
        n -= 4;
    }
    while (n > 0) {
        v = p[0]; q[0] = v; q[1] = v;
        q += 2;
        p += 1;
        n--;
    }
}

/* XXX: should use more abstract 'N' channels system */
static void stereo_split(short *output1, short *output2, short *input, int n)
{
    int i;

    for(i=0;i<n;i++) {
        *output1++ = *input++;
        *output2++ = *input++;
    }
}

static void stereo_mux(short *output, short *input1, short *input2, int n)
{
    int i;

    for(i=0;i<n;i++) {
        *output++ = *input1++;
        *output++ = *input2++;
    }
}

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
static void ac3_5p1_mux(short *output, short *input1, short *input2, int n)
{
    int i;
    short l,r;

    for(i=0;i<n;i++) {
      l=*input1++;
      r=*input2++;
      *output++ = l;           /* left */
      *output++ = (l/2)+(r/2); /* center */
      *output++ = r;           /* right */
      *output++ = 0;           /* left surround */
      *output++ = 0;           /* right surroud */
      *output++ = 0;           /* low freq */
    }
}

145 146
ReSampleContext *av_audio_resample_init(int output_channels, int input_channels,
                                        int output_rate, int input_rate,
147 148
                                        enum AVSampleFormat sample_fmt_out,
                                        enum AVSampleFormat sample_fmt_in,
149 150
                                        int filter_length, int log2_phase_count,
                                        int linear, double cutoff)
Fabrice Bellard's avatar
Fabrice Bellard committed
151 152
{
    ReSampleContext *s;
153

154 155
    if ( input_channels > 2)
      {
156
        av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.\n");
157
        return NULL;
158
      }
Fabrice Bellard's avatar
Fabrice Bellard committed
159 160 161

    s = av_mallocz(sizeof(ReSampleContext));
    if (!s)
162
      {
163
        av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context.\n");
164
        return NULL;
165
      }
Fabrice Bellard's avatar
Fabrice Bellard committed
166 167

    s->ratio = (float)output_rate / (float)input_rate;
168

Fabrice Bellard's avatar
Fabrice Bellard committed
169 170
    s->input_channels = input_channels;
    s->output_channels = output_channels;
171

Fabrice Bellard's avatar
Fabrice Bellard committed
172 173 174 175
    s->filter_channels = s->input_channels;
    if (s->output_channels < s->filter_channels)
        s->filter_channels = s->output_channels;

176 177
    s->sample_fmt [0] = sample_fmt_in;
    s->sample_fmt [1] = sample_fmt_out;
178 179
    s->sample_size[0] = av_get_bits_per_sample_fmt(s->sample_fmt[0])>>3;
    s->sample_size[1] = av_get_bits_per_sample_fmt(s->sample_fmt[1])>>3;
180

181 182
    if (s->sample_fmt[0] != AV_SAMPLE_FMT_S16) {
        if (!(s->convert_ctx[0] = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1,
183 184 185
                                                         s->sample_fmt[0], 1, NULL, 0))) {
            av_log(s, AV_LOG_ERROR,
                   "Cannot convert %s sample format to s16 sample format\n",
186
                   av_get_sample_fmt_name(s->sample_fmt[0]));
187 188 189 190 191
            av_free(s);
            return NULL;
        }
    }

192
    if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) {
193
        if (!(s->convert_ctx[1] = av_audio_convert_alloc(s->sample_fmt[1], 1,
194
                                                         AV_SAMPLE_FMT_S16, 1, NULL, 0))) {
195 196
            av_log(s, AV_LOG_ERROR,
                   "Cannot convert s16 sample format to %s sample format\n",
197
                   av_get_sample_fmt_name(s->sample_fmt[1]));
198 199 200 201 202 203
            av_audio_convert_free(s->convert_ctx[0]);
            av_free(s);
            return NULL;
        }
    }

204
/*
205
 * AC-3 output is the only case where filter_channels could be greater than 2.
206 207 208 209 210 211
 * input channels can't be greater than 2, so resample the 2 channels and then
 * expand to 6 channels after the resampling.
 */
    if(s->filter_channels>2)
      s->filter_channels = 2;

212
#define TAPS 16
213 214 215
    s->resample_context= av_resample_init(output_rate, input_rate,
                         filter_length, log2_phase_count, linear, cutoff);

216
    *(const AVClass**)s->resample_context = &audioresample_context_class;
217

Fabrice Bellard's avatar
Fabrice Bellard committed
218 219 220
    return s;
}

221
#if FF_API_AUDIO_OLD
222 223 224 225 226
ReSampleContext *audio_resample_init(int output_channels, int input_channels,
                                     int output_rate, int input_rate)
{
    return av_audio_resample_init(output_channels, input_channels,
                                  output_rate, input_rate,
227
                                  AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16,
228 229 230 231
                                  TAPS, 10, 0, 0.8);
}
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
232 233 234 235 236
/* resample audio. 'nb_samples' is the number of input samples */
/* XXX: optimize it ! */
int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples)
{
    int i, nb_samples1;
Fabrice Bellard's avatar
Fabrice Bellard committed
237 238
    short *bufin[2];
    short *bufout[2];
Fabrice Bellard's avatar
Fabrice Bellard committed
239
    short *buftmp2[2], *buftmp3[2];
240
    short *output_bak = NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
241
    int lenout;
Fabrice Bellard's avatar
Fabrice Bellard committed
242

243
    if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) {
Fabrice Bellard's avatar
Fabrice Bellard committed
244 245 246 247 248
        /* nothing to do */
        memcpy(output, input, nb_samples * s->input_channels * sizeof(short));
        return nb_samples;
    }

249
    if (s->sample_fmt[0] != AV_SAMPLE_FMT_S16) {
250 251 252 253
        int istride[1] = { s->sample_size[0] };
        int ostride[1] = { 2 };
        const void *ibuf[1] = { input };
        void       *obuf[1];
254
        unsigned input_size = nb_samples*s->input_channels*2;
255 256 257 258 259 260

        if (!s->buffer_size[0] || s->buffer_size[0] < input_size) {
            av_free(s->buffer[0]);
            s->buffer_size[0] = input_size;
            s->buffer[0] = av_malloc(s->buffer_size[0]);
            if (!s->buffer[0]) {
261
                av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n");
262 263 264 265 266 267 268 269
                return 0;
            }
        }

        obuf[0] = s->buffer[0];

        if (av_audio_convert(s->convert_ctx[0], obuf, ostride,
                             ibuf, istride, nb_samples*s->input_channels) < 0) {
270
            av_log(s->resample_context, AV_LOG_ERROR, "Audio sample format conversion failed\n");
271 272 273 274 275 276
            return 0;
        }

        input  = s->buffer[0];
    }

277
    lenout= 2*s->output_channels*nb_samples * s->ratio + 16;
278

279
    if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) {
280 281 282 283 284 285 286
        output_bak = output;

        if (!s->buffer_size[1] || s->buffer_size[1] < lenout) {
            av_free(s->buffer[1]);
            s->buffer_size[1] = lenout;
            s->buffer[1] = av_malloc(s->buffer_size[1]);
            if (!s->buffer[1]) {
287
                av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n");
288 289 290 291 292 293 294
                return 0;
            }
        }

        output = s->buffer[1];
    }

Fabrice Bellard's avatar
Fabrice Bellard committed
295
    /* XXX: move those malloc to resample init code */
296
    for(i=0; i<s->filter_channels; i++){
297
        bufin[i]= av_malloc( (nb_samples + s->temp_len) * sizeof(short) );
298 299 300
        memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short));
        buftmp2[i] = bufin[i] + s->temp_len;
    }
301

Fabrice Bellard's avatar
Fabrice Bellard committed
302
    /* make some zoom to avoid round pb */
303 304
    bufout[0]= av_malloc( lenout * sizeof(short) );
    bufout[1]= av_malloc( lenout * sizeof(short) );
Fabrice Bellard's avatar
Fabrice Bellard committed
305

Fabrice Bellard's avatar
Fabrice Bellard committed
306 307 308 309
    if (s->input_channels == 2 &&
        s->output_channels == 1) {
        buftmp3[0] = output;
        stereo_to_mono(buftmp2[0], input, nb_samples);
310
    } else if (s->output_channels >= 2 && s->input_channels == 1) {
Fabrice Bellard's avatar
Fabrice Bellard committed
311
        buftmp3[0] = bufout[0];
312
        memcpy(buftmp2[0], input, nb_samples*sizeof(short));
313
    } else if (s->output_channels >= 2) {
Fabrice Bellard's avatar
Fabrice Bellard committed
314 315 316 317 318
        buftmp3[0] = bufout[0];
        buftmp3[1] = bufout[1];
        stereo_split(buftmp2[0], buftmp2[1], input, nb_samples);
    } else {
        buftmp3[0] = output;
319
        memcpy(buftmp2[0], input, nb_samples*sizeof(short));
Fabrice Bellard's avatar
Fabrice Bellard committed
320 321
    }

322 323
    nb_samples += s->temp_len;

Fabrice Bellard's avatar
Fabrice Bellard committed
324 325 326
    /* resample each channel */
    nb_samples1 = 0; /* avoid warning */
    for(i=0;i<s->filter_channels;i++) {
327 328 329 330 331 332 333
        int consumed;
        int is_last= i+1 == s->filter_channels;

        nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], &consumed, nb_samples, lenout, is_last);
        s->temp_len= nb_samples - consumed;
        s->temp[i]= av_realloc(s->temp[i], s->temp_len*sizeof(short));
        memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short));
Fabrice Bellard's avatar
Fabrice Bellard committed
334 335 336 337 338 339
    }

    if (s->output_channels == 2 && s->input_channels == 1) {
        mono_to_stereo(output, buftmp3[0], nb_samples1);
    } else if (s->output_channels == 2) {
        stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
340 341
    } else if (s->output_channels == 6) {
        ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
Fabrice Bellard's avatar
Fabrice Bellard committed
342 343
    }

344
    if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) {
345 346 347 348 349 350 351
        int istride[1] = { 2 };
        int ostride[1] = { s->sample_size[1] };
        const void *ibuf[1] = { output };
        void       *obuf[1] = { output_bak };

        if (av_audio_convert(s->convert_ctx[1], obuf, ostride,
                             ibuf, istride, nb_samples1*s->output_channels) < 0) {
352
            av_log(s->resample_context, AV_LOG_ERROR, "Audio sample format convertion failed\n");
353 354 355 356
            return 0;
        }
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
357 358
    for(i=0; i<s->filter_channels; i++)
        av_free(bufin[i]);
Fabrice Bellard's avatar
Fabrice Bellard committed
359

360 361
    av_free(bufout[0]);
    av_free(bufout[1]);
Fabrice Bellard's avatar
Fabrice Bellard committed
362 363 364 365 366
    return nb_samples1;
}

void audio_resample_close(ReSampleContext *s)
{
367 368 369
    av_resample_close(s->resample_context);
    av_freep(&s->temp[0]);
    av_freep(&s->temp[1]);
370 371 372 373
    av_freep(&s->buffer[0]);
    av_freep(&s->buffer[1]);
    av_audio_convert_free(s->convert_ctx[0]);
    av_audio_convert_free(s->convert_ctx[1]);
374
    av_free(s);
Fabrice Bellard's avatar
Fabrice Bellard committed
375
}