ffmpeg / libavcodec / resample.c @ 18f77016
History  View  Annotate  Download (7.96 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 
#include "avcodec.h" 
20  
21 
typedef struct { 
22 
/* fractional resampling */

23 
UINT32 incr; /* fractional increment */

24 
UINT32 frac; 
25 
int last_sample;

26 
/* integer down sample */

27 
int iratio; /* integer divison ratio */ 
28 
int icount, isum;

29 
int inv;

30 
} ReSampleChannelContext; 
31  
32 
struct ReSampleContext {

33 
ReSampleChannelContext channel_ctx[2];

34 
float ratio;

35 
/* channel convert */

36 
int input_channels, output_channels, filter_channels;

37 
}; 
38  
39  
40 
#define FRAC_BITS 16 
41 
#define FRAC (1 << FRAC_BITS) 
42  
43 
static void init_mono_resample(ReSampleChannelContext *s, float ratio) 
44 
{ 
45 
ratio = 1.0 / ratio; 
46 
s>iratio = (int)floor(ratio);

47 
if (s>iratio == 0) 
48 
s>iratio = 1;

49 
s>incr = (int)((ratio / s>iratio) * FRAC);

50 
s>frac = FRAC; 
51 
s>last_sample = 0;

52 
s>icount = s>iratio; 
53 
s>isum = 0;

54 
s>inv = (FRAC / s>iratio); 
55 
} 
56  
57 
/* fractional audio resampling */

58 
static int fractional_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) 
59 
{ 
60 
unsigned int frac, incr; 
61 
int l0, l1;

62 
short *q, *p, *pend;

63  
64 
l0 = s>last_sample; 
65 
incr = s>incr; 
66 
frac = s>frac; 
67  
68 
p = input; 
69 
pend = input + nb_samples; 
70 
q = output; 
71  
72 
l1 = *p++; 
73 
for(;;) {

74 
/* interpolate */

75 
*q++ = (l0 * (FRAC  frac) + l1 * frac) >> FRAC_BITS; 
76 
frac = frac + s>incr; 
77 
while (frac >= FRAC) {

78 
frac = FRAC; 
79 
if (p >= pend)

80 
goto the_end;

81 
l0 = l1; 
82 
l1 = *p++; 
83 
} 
84 
} 
85 
the_end:

86 
s>last_sample = l1; 
87 
s>frac = frac; 
88 
return q  output;

89 
} 
90  
91 
static int integer_downsample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) 
92 
{ 
93 
short *q, *p, *pend;

94 
int c, sum;

95  
96 
p = input; 
97 
pend = input + nb_samples; 
98 
q = output; 
99  
100 
c = s>icount; 
101 
sum = s>isum; 
102  
103 
for(;;) {

104 
sum += *p++; 
105 
if (c == 0) { 
106 
*q++ = (sum * s>inv) >> FRAC_BITS; 
107 
c = s>iratio; 
108 
sum = 0;

109 
} 
110 
if (p >= pend)

111 
break;

112 
} 
113 
s>isum = sum; 
114 
s>icount = c; 
115 
return q  output;

116 
} 
117  
118 
/* n1: number of samples */

119 
static void stereo_to_mono(short *output, short *input, int n1) 
120 
{ 
121 
short *p, *q;

122 
int n = n1;

123  
124 
p = input; 
125 
q = output; 
126 
while (n >= 4) { 
127 
q[0] = (p[0] + p[1]) >> 1; 
128 
q[1] = (p[2] + p[3]) >> 1; 
129 
q[2] = (p[4] + p[5]) >> 1; 
130 
q[3] = (p[6] + p[7]) >> 1; 
131 
q += 4;

132 
p += 8;

133 
n = 4;

134 
} 
135 
while (n > 0) { 
136 
q[0] = (p[0] + p[1]) >> 1; 
137 
q++; 
138 
p += 2;

139 
n; 
140 
} 
141 
} 
142  
143 
/* n1: number of samples */

144 
static void mono_to_stereo(short *output, short *input, int n1) 
145 
{ 
146 
short *p, *q;

147 
int n = n1;

148 
int v;

149  
150 
p = input; 
151 
q = output; 
152 
while (n >= 4) { 
153 
v = p[0]; q[0] = v; q[1] = v; 
154 
v = p[1]; q[2] = v; q[3] = v; 
155 
v = p[2]; q[4] = v; q[5] = v; 
156 
v = p[3]; q[6] = v; q[7] = v; 
157 
q += 8;

158 
p += 4;

159 
n = 4;

160 
} 
161 
while (n > 0) { 
162 
v = p[0]; q[0] = v; q[1] = v; 
163 
q += 2;

164 
p += 1;

165 
n; 
166 
} 
167 
} 
168  
169 
/* XXX: should use more abstract 'N' channels system */

170 
static void stereo_split(short *output1, short *output2, short *input, int n) 
171 
{ 
172 
int i;

173  
174 
for(i=0;i<n;i++) { 
175 
*output1++ = *input++; 
176 
*output2++ = *input++; 
177 
} 
178 
} 
179  
180 
static void stereo_mux(short *output, short *input1, short *input2, int n) 
181 
{ 
182 
int i;

183  
184 
for(i=0;i<n;i++) { 
185 
*output++ = *input1++; 
186 
*output++ = *input2++; 
187 
} 
188 
} 
189  
190 
static int mono_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) 
191 
{ 
192 
short *buf1;

193 
short *buftmp;

194  
195 
buf1= (short*)av_malloc( nb_samples * sizeof(short) ); 
196  
197 
/* first downsample by an integer factor with averaging filter */

198 
if (s>iratio > 1) { 
199 
buftmp = buf1; 
200 
nb_samples = integer_downsample(s, buftmp, input, nb_samples); 
201 
} else {

202 
buftmp = input; 
203 
} 
204  
205 
/* then do a fractional resampling with linear interpolation */

206 
if (s>incr != FRAC) {

207 
nb_samples = fractional_resample(s, output, buftmp, nb_samples); 
208 
} else {

209 
memcpy(output, buftmp, nb_samples * sizeof(short)); 
210 
} 
211 
av_free(buf1); 
212 
return nb_samples;

213 
} 
214  
215 
ReSampleContext *audio_resample_init(int output_channels, int input_channels, 
216 
int output_rate, int input_rate) 
217 
{ 
218 
ReSampleContext *s; 
219 
int i;

220 

221 
if (output_channels > 2  input_channels > 2) 
222 
return NULL; 
223  
224 
s = av_mallocz(sizeof(ReSampleContext));

225 
if (!s)

226 
return NULL; 
227  
228 
s>ratio = (float)output_rate / (float)input_rate; 
229 

230 
s>input_channels = input_channels; 
231 
s>output_channels = output_channels; 
232 

233 
s>filter_channels = s>input_channels; 
234 
if (s>output_channels < s>filter_channels)

235 
s>filter_channels = s>output_channels; 
236  
237 
for(i=0;i<s>filter_channels;i++) { 
238 
init_mono_resample(&s>channel_ctx[i], s>ratio); 
239 
} 
240 
return s;

241 
} 
242  
243 
/* resample audio. 'nb_samples' is the number of input samples */

244 
/* XXX: optimize it ! */

245 
/* XXX: do it with polyphase filters, since the quality here is

246 
HORRIBLE. Return the number of samples available in output */

247 
int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) 
248 
{ 
249 
int i, nb_samples1;

250 
short *bufin[2]; 
251 
short *bufout[2]; 
252 
short *buftmp2[2], *buftmp3[2]; 
253 
int lenout;

254  
255 
if (s>input_channels == s>output_channels && s>ratio == 1.0) { 
256 
/* nothing to do */

257 
memcpy(output, input, nb_samples * s>input_channels * sizeof(short)); 
258 
return nb_samples;

259 
} 
260  
261 
/* XXX: move those malloc to resample init code */

262 
bufin[0]= (short*) av_malloc( nb_samples * sizeof(short) ); 
263 
bufin[1]= (short*) av_malloc( nb_samples * sizeof(short) ); 
264 

265 
/* make some zoom to avoid round pb */

266 
lenout= (int)(nb_samples * s>ratio) + 16; 
267 
bufout[0]= (short*) av_malloc( lenout * sizeof(short) ); 
268 
bufout[1]= (short*) av_malloc( lenout * sizeof(short) ); 
269  
270 
if (s>input_channels == 2 && 
271 
s>output_channels == 1) {

272 
buftmp2[0] = bufin[0]; 
273 
buftmp3[0] = output;

274 
stereo_to_mono(buftmp2[0], input, nb_samples);

275 
} else if (s>output_channels == 2 && s>input_channels == 1) { 
276 
buftmp2[0] = input;

277 
buftmp3[0] = bufout[0]; 
278 
} else if (s>output_channels == 2) { 
279 
buftmp2[0] = bufin[0]; 
280 
buftmp2[1] = bufin[1]; 
281 
buftmp3[0] = bufout[0]; 
282 
buftmp3[1] = bufout[1]; 
283 
stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); 
284 
} else {

285 
buftmp2[0] = input;

286 
buftmp3[0] = output;

287 
} 
288  
289 
/* resample each channel */

290 
nb_samples1 = 0; /* avoid warning */ 
291 
for(i=0;i<s>filter_channels;i++) { 
292 
nb_samples1 = mono_resample(&s>channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples); 
293 
} 
294  
295 
if (s>output_channels == 2 && s>input_channels == 1) { 
296 
mono_to_stereo(output, buftmp3[0], nb_samples1);

297 
} else if (s>output_channels == 2) { 
298 
stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1); 
299 
} 
300  
301 
av_free(bufin[0]);

302 
av_free(bufin[1]);

303  
304 
av_free(bufout[0]);

305 
av_free(bufout[1]);

306 
return nb_samples1;

307 
} 
308  
309 
void audio_resample_close(ReSampleContext *s)

310 
{ 
311 
av_free(s); 
312 
} 