Statistics
| Branch: | Revision:

ffmpeg / libavcodec / resample.c @ 983e3246

History | View | Annotate | Download (8.05 KB)

1
/*
2
 * Sample rate convertion for both audio and video
3
 * Copyright (c) 2000 Fabrice Bellard.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19

    
20
/**
21
 * @file resample.c
22
 * Sample rate convertion for both audio and video.
23
 */
24

    
25
#include "avcodec.h"
26

    
27
typedef struct {
28
    /* fractional resampling */
29
    uint32_t incr; /* fractional increment */
30
    uint32_t frac;
31
    int last_sample;
32
    /* integer down sample */
33
    int iratio;  /* integer divison ratio */
34
    int icount, isum;
35
    int inv;
36
} ReSampleChannelContext;
37

    
38
struct ReSampleContext {
39
    ReSampleChannelContext channel_ctx[2];
40
    float ratio;
41
    /* channel convert */
42
    int input_channels, output_channels, filter_channels;
43
};
44

    
45

    
46
#define FRAC_BITS 16
47
#define FRAC (1 << FRAC_BITS)
48

    
49
static void init_mono_resample(ReSampleChannelContext *s, float ratio)
50
{
51
    ratio = 1.0 / ratio;
52
    s->iratio = (int)floorf(ratio);
53
    if (s->iratio == 0)
54
        s->iratio = 1;
55
    s->incr = (int)((ratio / s->iratio) * FRAC);
56
    s->frac = FRAC;
57
    s->last_sample = 0;
58
    s->icount = s->iratio;
59
    s->isum = 0;
60
    s->inv = (FRAC / s->iratio);
61
}
62

    
63
/* fractional audio resampling */
64
static int fractional_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
65
{
66
    unsigned int frac, incr;
67
    int l0, l1;
68
    short *q, *p, *pend;
69

    
70
    l0 = s->last_sample;
71
    incr = s->incr;
72
    frac = s->frac;
73

    
74
    p = input;
75
    pend = input + nb_samples;
76
    q = output;
77

    
78
    l1 = *p++;
79
    for(;;) {
80
        /* interpolate */
81
        *q++ = (l0 * (FRAC - frac) + l1 * frac) >> FRAC_BITS;
82
        frac = frac + s->incr;
83
        while (frac >= FRAC) {
84
            frac -= FRAC;
85
            if (p >= pend)
86
                goto the_end;
87
            l0 = l1;
88
            l1 = *p++;
89
        }
90
    }
91
 the_end:
92
    s->last_sample = l1;
93
    s->frac = frac;
94
    return q - output;
95
}
96

    
97
static int integer_downsample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
98
{
99
    short *q, *p, *pend;
100
    int c, sum;
101

    
102
    p = input;
103
    pend = input + nb_samples;
104
    q = output;
105

    
106
    c = s->icount;
107
    sum = s->isum;
108

    
109
    for(;;) {
110
        sum += *p++;
111
        if (--c == 0) {
112
            *q++ = (sum * s->inv) >> FRAC_BITS;
113
            c = s->iratio;
114
            sum = 0;
115
        }
116
        if (p >= pend)
117
            break;
118
    }
119
    s->isum = sum;
120
    s->icount = c;
121
    return q - output;
122
}
123

    
124
/* n1: number of samples */
125
static void stereo_to_mono(short *output, short *input, int n1)
126
{
127
    short *p, *q;
128
    int n = n1;
129

    
130
    p = input;
131
    q = output;
132
    while (n >= 4) {
133
        q[0] = (p[0] + p[1]) >> 1;
134
        q[1] = (p[2] + p[3]) >> 1;
135
        q[2] = (p[4] + p[5]) >> 1;
136
        q[3] = (p[6] + p[7]) >> 1;
137
        q += 4;
138
        p += 8;
139
        n -= 4;
140
    }
141
    while (n > 0) {
142
        q[0] = (p[0] + p[1]) >> 1;
143
        q++;
144
        p += 2;
145
        n--;
146
    }
147
}
148

    
149
/* n1: number of samples */
150
static void mono_to_stereo(short *output, short *input, int n1)
151
{
152
    short *p, *q;
153
    int n = n1;
154
    int v;
155

    
156
    p = input;
157
    q = output;
158
    while (n >= 4) {
159
        v = p[0]; q[0] = v; q[1] = v;
160
        v = p[1]; q[2] = v; q[3] = v;
161
        v = p[2]; q[4] = v; q[5] = v;
162
        v = p[3]; q[6] = v; q[7] = v;
163
        q += 8;
164
        p += 4;
165
        n -= 4;
166
    }
167
    while (n > 0) {
168
        v = p[0]; q[0] = v; q[1] = v;
169
        q += 2;
170
        p += 1;
171
        n--;
172
    }
173
}
174

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

    
180
    for(i=0;i<n;i++) {
181
        *output1++ = *input++;
182
        *output2++ = *input++;
183
    }
184
}
185

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

    
190
    for(i=0;i<n;i++) {
191
        *output++ = *input1++;
192
        *output++ = *input2++;
193
    }
194
}
195

    
196
static int mono_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
197
{
198
    short *buf1;
199
    short *buftmp;
200

    
201
    buf1= (short*)av_malloc( nb_samples * sizeof(short) );
202

    
203
    /* first downsample by an integer factor with averaging filter */
204
    if (s->iratio > 1) {
205
        buftmp = buf1;
206
        nb_samples = integer_downsample(s, buftmp, input, nb_samples);
207
    } else {
208
        buftmp = input;
209
    }
210

    
211
    /* then do a fractional resampling with linear interpolation */
212
    if (s->incr != FRAC) {
213
        nb_samples = fractional_resample(s, output, buftmp, nb_samples);
214
    } else {
215
        memcpy(output, buftmp, nb_samples * sizeof(short));
216
    }
217
    av_free(buf1);
218
    return nb_samples;
219
}
220

    
221
ReSampleContext *audio_resample_init(int output_channels, int input_channels, 
222
                                      int output_rate, int input_rate)
223
{
224
    ReSampleContext *s;
225
    int i;
226
    
227
    if (output_channels > 2 || input_channels > 2)
228
        return NULL;
229

    
230
    s = av_mallocz(sizeof(ReSampleContext));
231
    if (!s)
232
        return NULL;
233

    
234
    s->ratio = (float)output_rate / (float)input_rate;
235
    
236
    s->input_channels = input_channels;
237
    s->output_channels = output_channels;
238
    
239
    s->filter_channels = s->input_channels;
240
    if (s->output_channels < s->filter_channels)
241
        s->filter_channels = s->output_channels;
242

    
243
    for(i=0;i<s->filter_channels;i++) {
244
        init_mono_resample(&s->channel_ctx[i], s->ratio);
245
    }
246
    return s;
247
}
248

    
249
/* resample audio. 'nb_samples' is the number of input samples */
250
/* XXX: optimize it ! */
251
/* XXX: do it with polyphase filters, since the quality here is
252
   HORRIBLE. Return the number of samples available in output */
253
int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples)
254
{
255
    int i, nb_samples1;
256
    short *bufin[2];
257
    short *bufout[2];
258
    short *buftmp2[2], *buftmp3[2];
259
    int lenout;
260

    
261
    if (s->input_channels == s->output_channels && s->ratio == 1.0) {
262
        /* nothing to do */
263
        memcpy(output, input, nb_samples * s->input_channels * sizeof(short));
264
        return nb_samples;
265
    }
266

    
267
    /* XXX: move those malloc to resample init code */
268
    bufin[0]= (short*) av_malloc( nb_samples * sizeof(short) );
269
    bufin[1]= (short*) av_malloc( nb_samples * sizeof(short) );
270
    
271
    /* make some zoom to avoid round pb */
272
    lenout= (int)(nb_samples * s->ratio) + 16;
273
    bufout[0]= (short*) av_malloc( lenout * sizeof(short) );
274
    bufout[1]= (short*) av_malloc( lenout * sizeof(short) );
275

    
276
    if (s->input_channels == 2 &&
277
        s->output_channels == 1) {
278
        buftmp2[0] = bufin[0];
279
        buftmp3[0] = output;
280
        stereo_to_mono(buftmp2[0], input, nb_samples);
281
    } else if (s->output_channels == 2 && s->input_channels == 1) {
282
        buftmp2[0] = input;
283
        buftmp3[0] = bufout[0];
284
    } else if (s->output_channels == 2) {
285
        buftmp2[0] = bufin[0];
286
        buftmp2[1] = bufin[1];
287
        buftmp3[0] = bufout[0];
288
        buftmp3[1] = bufout[1];
289
        stereo_split(buftmp2[0], buftmp2[1], input, nb_samples);
290
    } else {
291
        buftmp2[0] = input;
292
        buftmp3[0] = output;
293
    }
294

    
295
    /* resample each channel */
296
    nb_samples1 = 0; /* avoid warning */
297
    for(i=0;i<s->filter_channels;i++) {
298
        nb_samples1 = mono_resample(&s->channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples);
299
    }
300

    
301
    if (s->output_channels == 2 && s->input_channels == 1) {
302
        mono_to_stereo(output, buftmp3[0], nb_samples1);
303
    } else if (s->output_channels == 2) {
304
        stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
305
    }
306

    
307
    av_free(bufin[0]);
308
    av_free(bufin[1]);
309

    
310
    av_free(bufout[0]);
311
    av_free(bufout[1]);
312
    return nb_samples1;
313
}
314

    
315
void audio_resample_close(ReSampleContext *s)
316
{
317
    av_free(s);
318
}