Mercurial > libavcodec.hg
comparison resample.c @ 2082:3dc9bbe1b152 libavcodec
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
author | michael |
---|---|
date | Thu, 17 Jun 2004 15:43:23 +0000 |
parents | 932d306bf1dc |
children | db6a5e3e74a0 |
comparison
equal
deleted
inserted
replaced
2081:d3015863f745 | 2082:3dc9bbe1b152 |
---|---|
22 * Sample rate convertion for both audio and video. | 22 * Sample rate convertion for both audio and video. |
23 */ | 23 */ |
24 | 24 |
25 #include "avcodec.h" | 25 #include "avcodec.h" |
26 | 26 |
27 typedef struct { | 27 struct AVResampleContext; |
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 | 28 |
38 struct ReSampleContext { | 29 struct ReSampleContext { |
39 ReSampleChannelContext channel_ctx[2]; | 30 struct AVResampleContext *resample_context; |
31 short *temp[2]; | |
32 int temp_len; | |
40 float ratio; | 33 float ratio; |
41 /* channel convert */ | 34 /* channel convert */ |
42 int input_channels, output_channels, filter_channels; | 35 int input_channels, output_channels, filter_channels; |
43 }; | 36 }; |
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 | 37 |
124 /* n1: number of samples */ | 38 /* n1: number of samples */ |
125 static void stereo_to_mono(short *output, short *input, int n1) | 39 static void stereo_to_mono(short *output, short *input, int n1) |
126 { | 40 { |
127 short *p, *q; | 41 short *p, *q; |
208 *output++ = 0; /* right surroud */ | 122 *output++ = 0; /* right surroud */ |
209 *output++ = 0; /* low freq */ | 123 *output++ = 0; /* low freq */ |
210 } | 124 } |
211 } | 125 } |
212 | 126 |
213 static int mono_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) | |
214 { | |
215 short *buf1; | |
216 short *buftmp; | |
217 | |
218 buf1= (short*)av_malloc( nb_samples * sizeof(short) ); | |
219 | |
220 /* first downsample by an integer factor with averaging filter */ | |
221 if (s->iratio > 1) { | |
222 buftmp = buf1; | |
223 nb_samples = integer_downsample(s, buftmp, input, nb_samples); | |
224 } else { | |
225 buftmp = input; | |
226 } | |
227 | |
228 /* then do a fractional resampling with linear interpolation */ | |
229 if (s->incr != FRAC) { | |
230 nb_samples = fractional_resample(s, output, buftmp, nb_samples); | |
231 } else { | |
232 memcpy(output, buftmp, nb_samples * sizeof(short)); | |
233 } | |
234 av_free(buf1); | |
235 return nb_samples; | |
236 } | |
237 | |
238 ReSampleContext *audio_resample_init(int output_channels, int input_channels, | 127 ReSampleContext *audio_resample_init(int output_channels, int input_channels, |
239 int output_rate, int input_rate) | 128 int output_rate, int input_rate) |
240 { | 129 { |
241 ReSampleContext *s; | 130 ReSampleContext *s; |
242 int i; | 131 int i; |
269 * expand to 6 channels after the resampling. | 158 * expand to 6 channels after the resampling. |
270 */ | 159 */ |
271 if(s->filter_channels>2) | 160 if(s->filter_channels>2) |
272 s->filter_channels = 2; | 161 s->filter_channels = 2; |
273 | 162 |
274 for(i=0;i<s->filter_channels;i++) { | 163 s->resample_context= av_resample_init(output_rate, input_rate); |
275 init_mono_resample(&s->channel_ctx[i], s->ratio); | 164 |
276 } | |
277 return s; | 165 return s; |
278 } | 166 } |
279 | 167 |
280 /* resample audio. 'nb_samples' is the number of input samples */ | 168 /* resample audio. 'nb_samples' is the number of input samples */ |
281 /* XXX: optimize it ! */ | 169 /* XXX: optimize it ! */ |
282 /* XXX: do it with polyphase filters, since the quality here is | |
283 HORRIBLE. Return the number of samples available in output */ | |
284 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | 170 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) |
285 { | 171 { |
286 int i, nb_samples1; | 172 int i, nb_samples1; |
287 short *bufin[2]; | 173 short *bufin[2]; |
288 short *bufout[2]; | 174 short *bufout[2]; |
294 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); | 180 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); |
295 return nb_samples; | 181 return nb_samples; |
296 } | 182 } |
297 | 183 |
298 /* XXX: move those malloc to resample init code */ | 184 /* XXX: move those malloc to resample init code */ |
299 bufin[0]= (short*) av_malloc( nb_samples * sizeof(short) ); | 185 for(i=0; i<s->filter_channels; i++){ |
300 bufin[1]= (short*) av_malloc( nb_samples * sizeof(short) ); | 186 bufin[i]= (short*) av_malloc( (nb_samples + s->temp_len) * sizeof(short) ); |
187 memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short)); | |
188 buftmp2[i] = bufin[i] + s->temp_len; | |
189 } | |
301 | 190 |
302 /* make some zoom to avoid round pb */ | 191 /* make some zoom to avoid round pb */ |
303 lenout= (int)(nb_samples * s->ratio) + 16; | 192 lenout= (int)(nb_samples * s->ratio) + 16; |
304 bufout[0]= (short*) av_malloc( lenout * sizeof(short) ); | 193 bufout[0]= (short*) av_malloc( lenout * sizeof(short) ); |
305 bufout[1]= (short*) av_malloc( lenout * sizeof(short) ); | 194 bufout[1]= (short*) av_malloc( lenout * sizeof(short) ); |
306 | 195 |
307 if (s->input_channels == 2 && | 196 if (s->input_channels == 2 && |
308 s->output_channels == 1) { | 197 s->output_channels == 1) { |
309 buftmp2[0] = bufin[0]; | |
310 buftmp3[0] = output; | 198 buftmp3[0] = output; |
311 stereo_to_mono(buftmp2[0], input, nb_samples); | 199 stereo_to_mono(buftmp2[0], input, nb_samples); |
312 } else if (s->output_channels >= 2 && s->input_channels == 1) { | 200 } else if (s->output_channels >= 2 && s->input_channels == 1) { |
313 buftmp2[0] = input; | |
314 buftmp3[0] = bufout[0]; | 201 buftmp3[0] = bufout[0]; |
202 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); | |
315 } else if (s->output_channels >= 2) { | 203 } else if (s->output_channels >= 2) { |
316 buftmp2[0] = bufin[0]; | |
317 buftmp2[1] = bufin[1]; | |
318 buftmp3[0] = bufout[0]; | 204 buftmp3[0] = bufout[0]; |
319 buftmp3[1] = bufout[1]; | 205 buftmp3[1] = bufout[1]; |
320 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); | 206 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); |
321 } else { | 207 } else { |
322 buftmp2[0] = input; | |
323 buftmp3[0] = output; | 208 buftmp3[0] = output; |
324 } | 209 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
210 } | |
211 | |
212 nb_samples += s->temp_len; | |
325 | 213 |
326 /* resample each channel */ | 214 /* resample each channel */ |
327 nb_samples1 = 0; /* avoid warning */ | 215 nb_samples1 = 0; /* avoid warning */ |
328 for(i=0;i<s->filter_channels;i++) { | 216 for(i=0;i<s->filter_channels;i++) { |
329 nb_samples1 = mono_resample(&s->channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples); | 217 int consumed; |
218 int is_last= i+1 == s->filter_channels; | |
219 | |
220 nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], &consumed, nb_samples, lenout, is_last); | |
221 s->temp_len= nb_samples - consumed; | |
222 s->temp[i]= av_realloc(s->temp[i], s->temp_len*sizeof(short)); | |
223 memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short)); | |
330 } | 224 } |
331 | 225 |
332 if (s->output_channels == 2 && s->input_channels == 1) { | 226 if (s->output_channels == 2 && s->input_channels == 1) { |
333 mono_to_stereo(output, buftmp3[0], nb_samples1); | 227 mono_to_stereo(output, buftmp3[0], nb_samples1); |
334 } else if (s->output_channels == 2) { | 228 } else if (s->output_channels == 2) { |
345 return nb_samples1; | 239 return nb_samples1; |
346 } | 240 } |
347 | 241 |
348 void audio_resample_close(ReSampleContext *s) | 242 void audio_resample_close(ReSampleContext *s) |
349 { | 243 { |
244 av_resample_close(s->resample_context); | |
245 av_freep(&s->temp[0]); | |
246 av_freep(&s->temp[1]); | |
350 av_free(s); | 247 av_free(s); |
351 } | 248 } |