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 021111307 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 
} 