FFmpeg
resample_template.c
Go to the documentation of this file.
1 /*
2  * audio resampling
3  * Copyright (c) 2004-2012 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 #if defined(TEMPLATE_RESAMPLE_DBL)
29 
30 # define RENAME(N) N ## _double
31 # define FILTER_SHIFT 0
32 # define DELEM double
33 # define FELEM double
34 # define FELEM2 double
35 # define FOFFSET 0
36 # define OUT(d, v) d = v
37 
38 #elif defined(TEMPLATE_RESAMPLE_FLT)
39 
40 # define RENAME(N) N ## _float
41 # define FILTER_SHIFT 0
42 # define DELEM float
43 # define FELEM float
44 # define FELEM2 float
45 # define FOFFSET 0
46 # define OUT(d, v) d = v
47 
48 #elif defined(TEMPLATE_RESAMPLE_S32)
49 
50 # define RENAME(N) N ## _int32
51 # define FILTER_SHIFT 30
52 # define DELEM int32_t
53 # define FELEM int32_t
54 # define FELEM2 int64_t
55 # define FELEM_MAX INT32_MAX
56 # define FELEM_MIN INT32_MIN
57 # define FOFFSET (1<<(FILTER_SHIFT-1))
58 # define OUT(d, v) (d) = av_clipl_int32((v)>>FILTER_SHIFT)
59 
60 #elif defined(TEMPLATE_RESAMPLE_S16)
61 
62 # define RENAME(N) N ## _int16
63 # define FILTER_SHIFT 15
64 # define DELEM int16_t
65 # define FELEM int16_t
66 # define FELEM2 int32_t
67 # define FELEML int64_t
68 # define FELEM_MAX INT16_MAX
69 # define FELEM_MIN INT16_MIN
70 # define FOFFSET (1<<(FILTER_SHIFT-1))
71 # define OUT(d, v) (d) = av_clip_int16((v)>>FILTER_SHIFT)
72 
73 #endif
74 
75 static void RENAME(resample_one)(void *dest, const void *source,
76  int dst_size, int64_t index2, int64_t incr)
77 {
78  DELEM *dst = dest;
79  const DELEM *src = source;
80  int dst_index;
81 
82  for (dst_index = 0; dst_index < dst_size; dst_index++) {
83  dst[dst_index] = src[index2 >> 32];
84  index2 += incr;
85  }
86 }
87 
89  void *dest, const void *source,
90  int n, int update_ctx)
91 {
92  DELEM *dst = dest;
93  const DELEM *src = source;
94  int dst_index;
95  int index= c->index;
96  int frac= c->frac;
97  int sample_index = 0;
98 
99  while (index >= c->phase_count) {
100  sample_index++;
101  index -= c->phase_count;
102  }
103 
104  for (dst_index = 0; dst_index < n; dst_index++) {
105  FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
106 
107  FELEM2 val = FOFFSET;
108  FELEM2 val2= 0;
109  int i;
110  for (i = 0; i + 1 < c->filter_length; i+=2) {
111  val += src[sample_index + i ] * (FELEM2)filter[i ];
112  val2 += src[sample_index + i + 1] * (FELEM2)filter[i + 1];
113  }
114  if (i < c->filter_length)
115  val += src[sample_index + i ] * (FELEM2)filter[i ];
116 #ifdef FELEML
117  OUT(dst[dst_index], val + (FELEML)val2);
118 #else
119  OUT(dst[dst_index], val + val2);
120 #endif
121 
122  frac += c->dst_incr_mod;
123  index += c->dst_incr_div;
124  if (frac >= c->src_incr) {
125  frac -= c->src_incr;
126  index++;
127  }
128 
129  while (index >= c->phase_count) {
130  sample_index++;
131  index -= c->phase_count;
132  }
133  }
134 
135  if(update_ctx){
136  c->frac= frac;
137  c->index= index;
138  }
139 
140  return sample_index;
141 }
142 
144  void *dest, const void *source,
145  int n, int update_ctx)
146 {
147  DELEM *dst = dest;
148  const DELEM *src = source;
149  int dst_index;
150  int index= c->index;
151  int frac= c->frac;
152  int sample_index = 0;
153 #if FILTER_SHIFT == 0
154  double inv_src_incr = 1.0 / c->src_incr;
155 #endif
156 
157  while (index >= c->phase_count) {
158  sample_index++;
159  index -= c->phase_count;
160  }
161 
162  for (dst_index = 0; dst_index < n; dst_index++) {
163  FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
164  FELEM2 val = FOFFSET, v2 = FOFFSET;
165 
166  int i;
167  for (i = 0; i < c->filter_length; i++) {
168  val += src[sample_index + i] * (FELEM2)filter[i];
169  v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc];
170  }
171 #ifdef FELEML
172  val += (v2 - val) * (FELEML) frac / c->src_incr;
173 #else
174 # if FILTER_SHIFT == 0
175  val += (v2 - val) * inv_src_incr * frac;
176 # else
177  val += (v2 - val) / c->src_incr * frac;
178 # endif
179 #endif
180  OUT(dst[dst_index], val);
181 
182  frac += c->dst_incr_mod;
183  index += c->dst_incr_div;
184  if (frac >= c->src_incr) {
185  frac -= c->src_incr;
186  index++;
187  }
188 
189  while (index >= c->phase_count) {
190  sample_index++;
191  index -= c->phase_count;
192  }
193  }
194 
195  if(update_ctx){
196  c->frac= frac;
197  c->index= index;
198  }
199 
200  return sample_index;
201 }
202 
203 #undef RENAME
204 #undef FILTER_SHIFT
205 #undef DELEM
206 #undef FELEM
207 #undef FELEM2
208 #undef FELEML
209 #undef FELEM_MAX
210 #undef FELEM_MIN
211 #undef OUT
212 #undef FOFFSET
n
int n
Definition: avisynth_c.h:760
ResampleContext::frac
int frac
Definition: resample.h:36
ResampleContext::resample_common
int(* resample_common)(struct ResampleContext *c, void *dst, const void *src, int n, int update_ctx)
Definition: resample.h:56
resample_linear
static void SET_TYPE() resample_linear(ResampleContext *c, void *dst0, int dst_index, const void *src0, unsigned int index, int frac)
Definition: resample_template.c:64
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce 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
Definition: filter_design.txt:228
resample_one
static void SET_TYPE() resample_one(ResampleContext *c, void *dst0, int dst_index, const void *src0, unsigned int index, int frac)
Definition: resample_template.c:85
ResampleContext::filter_length
int filter_length
Definition: resample.h:32
src
#define src
Definition: vp8dsp.c:254
ResampleContext
Definition: af_resample.c:38
FELEML
#define FELEML
Definition: resample_template.c:52
index
int index
Definition: gxfenc.c:89
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
source
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a source
Definition: filter_design.txt:255
val
const char const char void * val
Definition: avisynth_c.h:863
OUT
@ OUT
Definition: af_loudnorm.c:38
FELEM2
#define FELEM2
Definition: resample_template.c:51
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
RENAME
#define RENAME(name)
Definition: ffv1.h:197
FELEM
#define FELEM
Definition: resample_template.c:50
FOFFSET
#define FOFFSET(x)
Definition: options.c:299