FFmpeg
celp_filters.c
Go to the documentation of this file.
1 /*
2  * various filters for ACELP-based codecs
3  *
4  * Copyright (c) 2008 Vladimir Voroshilov
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <stdint.h>
24 #include <string.h>
25 
26 #include "config.h"
27 #include "celp_filters.h"
28 #include "libavutil/avassert.h"
29 #include "libavutil/common.h"
30 
31 void ff_celp_convolve_circ(int16_t* fc_out, const int16_t* fc_in,
32  const int16_t* filter, int len)
33 {
34  int i, k;
35 
36  memset(fc_out, 0, len * sizeof(int16_t));
37 
38  /* Since there are few pulses over an entire subframe (i.e. almost
39  all fc_in[i] are zero) it is faster to loop over fc_in first. */
40  for (i = 0; i < len; i++) {
41  if (fc_in[i]) {
42  for (k = 0; k < i; k++)
43  fc_out[k] += (fc_in[i] * filter[len + k - i]) >> 15;
44 
45  for (k = i; k < len; k++)
46  fc_out[k] += (fc_in[i] * filter[ k - i]) >> 15;
47  }
48  }
49 }
50 
51 void ff_celp_circ_addf(float *out, const float *in,
52  const float *lagged, int lag, float fac, int n)
53 {
54  int k;
55  for (k = 0; k < lag; k++)
56  out[k] = in[k] + fac * lagged[n + k - lag];
57  for (; k < n; k++)
58  out[k] = in[k] + fac * lagged[ k - lag];
59 }
60 
61 int ff_celp_lp_synthesis_filter(int16_t *out, const int16_t *filter_coeffs,
62  const int16_t *in, int buffer_length,
63  int filter_length, int stop_on_overflow,
64  int shift, int rounder)
65 {
66  int i,n;
67 
68  for (n = 0; n < buffer_length; n++) {
69  int sum = rounder, sum1;
70  for (i = 1; i <= filter_length; i++)
71  sum -= (unsigned)(filter_coeffs[i-1] * out[n-i]);
72 
73  sum1 = ((sum >> 12) + in[n]) >> shift;
74  sum = av_clip_int16(sum1);
75 
76  if (stop_on_overflow && sum != sum1)
77  return 1;
78 
79  out[n] = sum;
80  }
81 
82  return 0;
83 }
84 
85 void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs,
86  const float* in, int buffer_length,
87  int filter_length)
88 {
89  int i,n;
90 
91 #if 0 // Unoptimized code path for improved readability
92  for (n = 0; n < buffer_length; n++) {
93  out[n] = in[n];
94  for (i = 1; i <= filter_length; i++)
95  out[n] -= filter_coeffs[i-1] * out[n-i];
96  }
97 #else
98  float out0, out1, out2, out3;
99  float old_out0, old_out1, old_out2, old_out3;
100  float a,b,c;
101 
102  a = filter_coeffs[0];
103  b = filter_coeffs[1];
104  c = filter_coeffs[2];
105  b -= filter_coeffs[0] * filter_coeffs[0];
106  c -= filter_coeffs[1] * filter_coeffs[0];
107  c -= filter_coeffs[0] * b;
108 
109  av_assert2((filter_length&1)==0 && filter_length>=4);
110 
111  old_out0 = out[-4];
112  old_out1 = out[-3];
113  old_out2 = out[-2];
114  old_out3 = out[-1];
115  for (n = 0; n <= buffer_length - 4; n+=4) {
116  float tmp0,tmp1,tmp2;
117  float val;
118 
119  out0 = in[0];
120  out1 = in[1];
121  out2 = in[2];
122  out3 = in[3];
123 
124  out0 -= filter_coeffs[2] * old_out1;
125  out1 -= filter_coeffs[2] * old_out2;
126  out2 -= filter_coeffs[2] * old_out3;
127 
128  out0 -= filter_coeffs[1] * old_out2;
129  out1 -= filter_coeffs[1] * old_out3;
130 
131  out0 -= filter_coeffs[0] * old_out3;
132 
133  val = filter_coeffs[3];
134 
135  out0 -= val * old_out0;
136  out1 -= val * old_out1;
137  out2 -= val * old_out2;
138  out3 -= val * old_out3;
139 
140  for (i = 5; i < filter_length; i += 2) {
141  old_out3 = out[-i];
142  val = filter_coeffs[i-1];
143 
144  out0 -= val * old_out3;
145  out1 -= val * old_out0;
146  out2 -= val * old_out1;
147  out3 -= val * old_out2;
148 
149  old_out2 = out[-i-1];
150 
151  val = filter_coeffs[i];
152 
153  out0 -= val * old_out2;
154  out1 -= val * old_out3;
155  out2 -= val * old_out0;
156  out3 -= val * old_out1;
157 
158  FFSWAP(float, old_out0, old_out2);
159  old_out1 = old_out3;
160  }
161 
162  tmp0 = out0;
163  tmp1 = out1;
164  tmp2 = out2;
165 
166  out3 -= a * tmp2;
167  out2 -= a * tmp1;
168  out1 -= a * tmp0;
169 
170  out3 -= b * tmp1;
171  out2 -= b * tmp0;
172 
173  out3 -= c * tmp0;
174 
175 
176  out[0] = out0;
177  out[1] = out1;
178  out[2] = out2;
179  out[3] = out3;
180 
181  old_out0 = out0;
182  old_out1 = out1;
183  old_out2 = out2;
184  old_out3 = out3;
185 
186  out += 4;
187  in += 4;
188  }
189 
190  out -= n;
191  in -= n;
192  for (; n < buffer_length; n++) {
193  out[n] = in[n];
194  for (i = 1; i <= filter_length; i++)
195  out[n] -= filter_coeffs[i-1] * out[n-i];
196  }
197 #endif
198 }
199 
200 void ff_celp_lp_zero_synthesis_filterf(float *out, const float *filter_coeffs,
201  const float *in, int buffer_length,
202  int filter_length)
203 {
204  int i,n;
205 
206  for (n = 0; n < buffer_length; n++) {
207  out[n] = in[n];
208  for (i = 1; i <= filter_length; i++)
209  out[n] += filter_coeffs[i-1] * in[n-i];
210  }
211 }
212 
214 {
215  c->celp_lp_synthesis_filterf = ff_celp_lp_synthesis_filterf;
216  c->celp_lp_zero_synthesis_filterf = ff_celp_lp_zero_synthesis_filterf;
217 
218 #if HAVE_MIPSFPU
220 #endif
221 }
out
FILE * out
Definition: movenc.c:54
b
#define b
Definition: input.c:41
ff_celp_lp_synthesis_filter
int ff_celp_lp_synthesis_filter(int16_t *out, const int16_t *filter_coeffs, const int16_t *in, int buffer_length, int filter_length, int stop_on_overflow, int shift, int rounder)
LP synthesis filter.
Definition: celp_filters.c:61
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
ff_celp_lp_synthesis_filterf
void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs, const float *in, int buffer_length, int filter_length)
LP synthesis filter.
Definition: celp_filters.c:85
val
static double val(void *priv, double ch)
Definition: aeval.c:78
avassert.h
av_clip_int16
#define av_clip_int16
Definition: common.h:113
ff_celp_convolve_circ
void ff_celp_convolve_circ(int16_t *fc_out, const int16_t *fc_in, const int16_t *filter, int len)
Circularly convolve fixed vector with a phase dispersion impulse response filter (D....
Definition: celp_filters.c:31
celp_filters.h
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
shift
static int shift(int a, int b)
Definition: bonk.c:262
CELPFContext
Definition: celp_filters.h:28
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
ff_celp_filter_init
void ff_celp_filter_init(CELPFContext *c)
Initialize CELPFContext.
Definition: celp_filters.c:213
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:67
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
common.h
len
int len
Definition: vorbis_enc_data.h:426
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
ff_celp_lp_zero_synthesis_filterf
void ff_celp_lp_zero_synthesis_filterf(float *out, const float *filter_coeffs, const float *in, int buffer_length, int filter_length)
LP zero synthesis filter.
Definition: celp_filters.c:200
ff_celp_circ_addf
void ff_celp_circ_addf(float *out, const float *in, const float *lagged, int lag, float fac, int n)
Add an array to a rotated array.
Definition: celp_filters.c:51
ff_celp_filter_init_mips
void ff_celp_filter_init_mips(CELPFContext *c)
Definition: celp_filters_mips.c:285