3 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
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.
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.
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
24 * @author Michael Niedermayer <michaelni@gmx.at>
30 #define PHASE_SHIFT 10
31 #define PHASE_COUNT (1<<PHASE_SHIFT)
32 #define PHASE_MASK (PHASE_COUNT-1)
33 #define FILTER_SHIFT 15
35 typedef struct AVResampleContext
{
43 int compensation_distance
;
47 * 0th order modified bessel function of the first kind.
49 double bessel(double x
){
56 v
+= pow(x
*x
/4, i
)/(t
*t
);
62 * builds a polyphase filterbank.
63 * @param factor resampling factor
64 * @param scale wanted sum of coefficients for each filter
65 * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2->kaiser windowed sinc beta=16
67 void av_build_filter(int16_t *filter
, double factor
, int tap_count
, int phase_count
, int scale
, int type
){
69 double x
, y
, w
, tab
[tap_count
];
70 const int center
= (tap_count
-1)/2;
72 /* if upsampling, only need to interpolate, no filter */
76 for(ph
=0;ph
<phase_count
;ph
++) {
79 for(i
=0;i
<tap_count
;i
++) {
80 x
= M_PI
* ((double)(i
- center
) - (double)ph
/ phase_count
) * factor
;
85 const float d
= -0.5; //first order derivative = -0.5
86 x
= fabs(((double)(i
- center
) - (double)ph
/ phase_count
) * factor
);
87 if(x
<1.0) y
= 1 - 3*x
*x
+ 2*x
*x
*x
+ d
*( -x
*x
+ x
*x
*x
);
88 else y
= d
*(-4 + 8*x
- 5*x
*x
+ x
*x
*x
);
91 w
= 2.0*x
/ (factor
*tap_count
) + M_PI
;
92 y
*= 0.3635819 - 0.4891775 * cos(w
) + 0.1365995 * cos(2*w
) - 0.0106411 * cos(3*w
);
95 w
= 2.0*x
/ (factor
*tap_count
*M_PI
);
96 y
*= bessel(16*sqrt(FFMAX(1-w
*w
, 0))) / bessel(16);
104 /* normalize so that an uniform color remains the same */
105 for(i
=0;i
<tap_count
;i
++) {
106 v
= clip(lrintf(tab
[i
] * scale
/ norm
) + e
, -32768, 32767);
107 filter
[ph
* tap_count
+ i
] = v
;
108 e
+= tab
[i
] * scale
/ norm
- v
;
114 * initalizes a audio resampler.
115 * note, if either rate is not a integer then simply scale both rates up so they are
117 AVResampleContext
*av_resample_init(int out_rate
, int in_rate
){
118 AVResampleContext
*c
= av_mallocz(sizeof(AVResampleContext
));
119 double factor
= FFMIN(out_rate
/ (double)in_rate
, 1.0);
121 memset(c
, 0, sizeof(AVResampleContext
));
123 c
->filter_length
= ceil(16.0/factor
);
124 c
->filter_bank
= av_mallocz(c
->filter_length
*(PHASE_COUNT
+1)*sizeof(short));
125 av_build_filter(c
->filter_bank
, factor
, c
->filter_length
, PHASE_COUNT
, 1<<FILTER_SHIFT
, 1);
126 c
->filter_bank
[c
->filter_length
*PHASE_COUNT
+ (c
->filter_length
-1) + 1]= (1<<FILTER_SHIFT
)-1;
127 c
->filter_bank
[c
->filter_length
*PHASE_COUNT
+ (c
->filter_length
-1) + 2]= 1;
129 c
->src_incr
= out_rate
;
130 c
->ideal_dst_incr
= c
->dst_incr
= in_rate
* PHASE_COUNT
;
131 c
->index
= -PHASE_COUNT
*((c
->filter_length
-1)/2);
136 void av_resample_close(AVResampleContext
*c
){
137 av_freep(&c
->filter_bank
);
141 void av_resample_compensate(AVResampleContext
*c
, int sample_delta
, int compensation_distance
){
142 assert(!c
->compensation_distance
); //FIXME
144 c
->compensation_distance
= compensation_distance
;
145 c
->dst_incr
-= c
->ideal_dst_incr
* sample_delta
/ compensation_distance
;
150 * @param src an array of unconsumed samples
151 * @param consumed the number of samples of src which have been consumed are returned here
152 * @param src_size the number of unconsumed samples available
153 * @param dst_size the amount of space in samples available in dst
154 * @param update_ctx if this is 0 then the context wont be modified, that way several channels can be resampled with the same context
155 * @return the number of samples written in dst or -1 if an error occured
157 int av_resample(AVResampleContext
*c
, short *dst
, short *src
, int *consumed
, int src_size
, int dst_size
, int update_ctx
){
161 int dst_incr_frac
= c
->dst_incr
% c
->src_incr
;
162 int dst_incr
= c
->dst_incr
/ c
->src_incr
;
164 if(c
->compensation_distance
&& c
->compensation_distance
< dst_size
)
165 dst_size
= c
->compensation_distance
;
167 for(dst_index
=0; dst_index
< dst_size
; dst_index
++){
168 short *filter
= c
->filter_bank
+ c
->filter_length
*(index
& PHASE_MASK
);
169 int sample_index
= index
>> PHASE_SHIFT
;
172 if(sample_index
< 0){
173 for(i
=0; i
<c
->filter_length
; i
++)
174 val
+= src
[ABS(sample_index
+ i
)] * filter
[i
];
175 }else if(sample_index
+ c
->filter_length
> src_size
){
180 int sub_phase
= (frac
<<12) / c
->src_incr
;
181 for(i
=0; i
<c
->filter_length
; i
++){
182 int64_t coeff
= filter
[i
]*(4096 - sub_phase
) + filter
[i
+ c
->filter_length
]*sub_phase
;
183 v
+= src
[sample_index
+ i
] * coeff
;
187 for(i
=0; i
<c
->filter_length
; i
++){
188 val
+= src
[sample_index
+ i
] * filter
[i
];
193 val
= (val
+ (1<<(FILTER_SHIFT
-1)))>>FILTER_SHIFT
;
194 dst
[dst_index
] = (unsigned)(val
+ 32768) > 65535 ?
(val
>>31) ^ 32767 : val
;
196 frac
+= dst_incr_frac
;
198 if(frac
>= c
->src_incr
){
204 if(c
->compensation_distance
){
205 c
->compensation_distance
-= index
;
206 if(!c
->compensation_distance
)
207 c
->dst_incr
= c
->ideal_dst_incr
;
212 *consumed
= index
>> PHASE_SHIFT
;