resample2.c
Go to the documentation of this file.
1 /*
2  * audio resampling
3  * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * audio resampling
25  * @author Michael Niedermayer <michaelni@gmx.at>
26  */
27 
28 #include "libavutil/avassert.h"
29 #include "avcodec.h"
30 #include "libavutil/common.h"
31 
32 #if FF_API_AVCODEC_RESAMPLE
33 
34 #ifndef CONFIG_RESAMPLE_HP
35 #define FILTER_SHIFT 15
36 
37 #define FELEM int16_t
38 #define FELEM2 int32_t
39 #define FELEML int64_t
40 #define FELEM_MAX INT16_MAX
41 #define FELEM_MIN INT16_MIN
42 #define WINDOW_TYPE 9
43 #elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE)
44 #define FILTER_SHIFT 30
45 
46 #define FELEM int32_t
47 #define FELEM2 int64_t
48 #define FELEML int64_t
49 #define FELEM_MAX INT32_MAX
50 #define FELEM_MIN INT32_MIN
51 #define WINDOW_TYPE 12
52 #else
53 #define FILTER_SHIFT 0
54 
55 #define FELEM double
56 #define FELEM2 double
57 #define FELEML double
58 #define WINDOW_TYPE 24
59 #endif
60 
61 
62 typedef struct AVResampleContext{
63  const AVClass *av_class;
65  int filter_length;
66  int ideal_dst_incr;
67  int dst_incr;
68  int index;
69  int frac;
70  int src_incr;
71  int compensation_distance;
72  int phase_shift;
73  int phase_mask;
74  int linear;
75 }AVResampleContext;
76 
77 /**
78  * 0th order modified bessel function of the first kind.
79  */
80 static double bessel(double x){
81  double v=1;
82  double lastv=0;
83  double t=1;
84  int i;
85 
86  x= x*x/4;
87  for(i=1; v != lastv; i++){
88  lastv=v;
89  t *= x/(i*i);
90  v += t;
91  }
92  return v;
93 }
94 
95 /**
96  * Build a polyphase filterbank.
97  * @param factor resampling factor
98  * @param scale wanted sum of coefficients for each filter
99  * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16
100  * @return 0 on success, negative on error
101  */
102 static int build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){
103  int ph, i;
104  double x, y, w;
105  double *tab = av_malloc(tap_count * sizeof(*tab));
106  const int center= (tap_count-1)/2;
107 
108  if (!tab)
109  return AVERROR(ENOMEM);
110 
111  /* if upsampling, only need to interpolate, no filter */
112  if (factor > 1.0)
113  factor = 1.0;
114 
115  for(ph=0;ph<phase_count;ph++) {
116  double norm = 0;
117  for(i=0;i<tap_count;i++) {
118  x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
119  if (x == 0) y = 1.0;
120  else y = sin(x) / x;
121  switch(type){
122  case 0:{
123  const float d= -0.5; //first order derivative = -0.5
124  x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
125  if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*( -x*x + x*x*x);
126  else y= d*(-4 + 8*x - 5*x*x + x*x*x);
127  break;}
128  case 1:
129  w = 2.0*x / (factor*tap_count) + M_PI;
130  y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
131  break;
132  default:
133  w = 2.0*x / (factor*tap_count*M_PI);
134  y *= bessel(type*sqrt(FFMAX(1-w*w, 0)));
135  break;
136  }
137 
138  tab[i] = y;
139  norm += y;
140  }
141 
142  /* normalize so that an uniform color remains the same */
143  for(i=0;i<tap_count;i++) {
144 #ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
145  filter[ph * tap_count + i] = tab[i] / norm;
146 #else
147  filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), FELEM_MIN, FELEM_MAX);
148 #endif
149  }
150  }
151 #if 0
152  {
153 #define LEN 1024
154  int j,k;
155  double sine[LEN + tap_count];
156  double filtered[LEN];
157  double maxff=-2, minff=2, maxsf=-2, minsf=2;
158  for(i=0; i<LEN; i++){
159  double ss=0, sf=0, ff=0;
160  for(j=0; j<LEN+tap_count; j++)
161  sine[j]= cos(i*j*M_PI/LEN);
162  for(j=0; j<LEN; j++){
163  double sum=0;
164  ph=0;
165  for(k=0; k<tap_count; k++)
166  sum += filter[ph * tap_count + k] * sine[k+j];
167  filtered[j]= sum / (1<<FILTER_SHIFT);
168  ss+= sine[j + center] * sine[j + center];
169  ff+= filtered[j] * filtered[j];
170  sf+= sine[j + center] * filtered[j];
171  }
172  ss= sqrt(2*ss/LEN);
173  ff= sqrt(2*ff/LEN);
174  sf= 2*sf/LEN;
175  maxff= FFMAX(maxff, ff);
176  minff= FFMIN(minff, ff);
177  maxsf= FFMAX(maxsf, sf);
178  minsf= FFMIN(minsf, sf);
179  if(i%11==0){
180  av_log(NULL, AV_LOG_ERROR, "i:%4d ss:%f ff:%13.6e-%13.6e sf:%13.6e-%13.6e\n", i, ss, maxff, minff, maxsf, minsf);
181  minff=minsf= 2;
182  maxff=maxsf= -2;
183  }
184  }
185  }
186 #endif
187 
188  av_free(tab);
189  return 0;
190 }
191 
192 AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){
193  AVResampleContext *c= av_mallocz(sizeof(AVResampleContext));
194  double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
195  int phase_count= 1<<phase_shift;
196 
197  if (!c)
198  return NULL;
199 
200  c->phase_shift= phase_shift;
201  c->phase_mask= phase_count-1;
202  c->linear= linear;
203 
204  c->filter_length= FFMAX((int)ceil(filter_size/factor), 1);
205  c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM));
206  if (!c->filter_bank)
207  goto error;
208  if (build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, WINDOW_TYPE))
209  goto error;
210  memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM));
211  c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1];
212 
213  if(!av_reduce(&c->src_incr, &c->dst_incr, out_rate, in_rate * (int64_t)phase_count, INT32_MAX/2))
214  goto error;
215  c->ideal_dst_incr= c->dst_incr;
216 
217  c->index= -phase_count*((c->filter_length-1)/2);
218 
219  return c;
220 error:
221  av_free(c->filter_bank);
222  av_free(c);
223  return NULL;
224 }
225 
226 void av_resample_close(AVResampleContext *c){
227  av_freep(&c->filter_bank);
228  av_freep(&c);
229 }
230 
231 void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){
232 // sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr;
233  c->compensation_distance= compensation_distance;
234  c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
235 }
236 
237 int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){
238  int dst_index, i;
239  int index= c->index;
240  int frac= c->frac;
241  int dst_incr_frac= c->dst_incr % c->src_incr;
242  int dst_incr= c->dst_incr / c->src_incr;
243  int compensation_distance= c->compensation_distance;
244 
245  if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){
246  int64_t index2= ((int64_t)index)<<32;
247  int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr;
248  dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr);
249 
250  for(dst_index=0; dst_index < dst_size; dst_index++){
251  dst[dst_index] = src[index2>>32];
252  index2 += incr;
253  }
254  index += dst_index * dst_incr;
255  index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr;
256  frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr;
257  }else{
258  for(dst_index=0; dst_index < dst_size; dst_index++){
259  FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask);
260  int sample_index= index >> c->phase_shift;
261  FELEM2 val=0;
262 
263  if(sample_index < 0){
264  for(i=0; i<c->filter_length; i++)
265  val += src[FFABS(sample_index + i) % src_size] * filter[i];
266  }else if(sample_index + c->filter_length > src_size){
267  break;
268  }else if(c->linear){
269  FELEM2 v2=0;
270  for(i=0; i<c->filter_length; i++){
271  val += src[sample_index + i] * (FELEM2)filter[i];
272  v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length];
273  }
274  val+=(v2-val)*(FELEML)frac / c->src_incr;
275  }else{
276  for(i=0; i<c->filter_length; i++){
277  val += src[sample_index + i] * (FELEM2)filter[i];
278  }
279  }
280 
281 #ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
282  dst[dst_index] = av_clip_int16(lrintf(val));
283 #else
284  val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
285  dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val;
286 #endif
287 
288  frac += dst_incr_frac;
289  index += dst_incr;
290  if(frac >= c->src_incr){
291  frac -= c->src_incr;
292  index++;
293  }
294 
295  if(dst_index + 1 == compensation_distance){
296  compensation_distance= 0;
297  dst_incr_frac= c->ideal_dst_incr % c->src_incr;
298  dst_incr= c->ideal_dst_incr / c->src_incr;
299  }
300  }
301  }
302  *consumed= FFMAX(index, 0) >> c->phase_shift;
303  if(index>=0) index &= c->phase_mask;
304 
305  if(compensation_distance){
306  compensation_distance -= dst_index;
307  av_assert2(compensation_distance > 0);
308  }
309  if(update_ctx){
310  c->frac= frac;
311  c->index= index;
312  c->dst_incr= dst_incr_frac + c->src_incr*dst_incr;
313  c->compensation_distance= compensation_distance;
314  }
315 
316  return dst_index;
317 }
318 
319 #endif
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
float v
output residual component w
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
set threshold d
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:63
the mask is usually to keep the same permissions Filters should remove permissions on reference they give to output whenever necessary It can be automatically done by setting the rej_perms field on the output pad Here are a few guidelines corresponding to common then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
#define lrintf(x)
Definition: libm_mips.h:70
integer sqrt
Definition: avutil.txt:2
static int16_t filter_bank[512]
Definition: mpegaudiotab.h:82
Discrete Time axis x
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
#define FFMAX(a, b)
Definition: common.h:56
external API header
static int build_filter(ResampleContext *c)
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:36
#define LEN
#define FFMIN(a, b)
Definition: common.h:58
t
Definition: genspecsines3.m:6
#define FFABS(a)
Definition: common.h:53
for k
NULL
Definition: eval.c:55
AVS_Value src
Definition: avisynth_c.h:523
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Describe the class of an AVClass context structure.
Definition: log.h:50
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
static const int factor[16]
Definition: vf_pp7.c:202
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
#define type
static const AVClass av_class
Definition: swresample.c:138
common internal and external API header
static double c[64]
Same thing on a dB scale
function y
Definition: D.m:1
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
static const struct twinvq_data tab
#define M_PI
Definition: mathematics.h:46
static double bessel(double x)