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/attributes.h"
29 #include "libavutil/avassert.h"
30 #include "libavutil/common.h"
31 
32 void ff_celp_convolve_circ(int16_t* fc_out, const int16_t* fc_in,
33  const int16_t* filter, int len)
34 {
35  int i, k;
36 
37  memset(fc_out, 0, len * sizeof(int16_t));
38 
39  /* Since there are few pulses over an entire subframe (i.e. almost
40  all fc_in[i] are zero) it is faster to loop over fc_in first. */
41  for (i = 0; i < len; i++) {
42  if (fc_in[i]) {
43  for (k = 0; k < i; k++)
44  fc_out[k] += (fc_in[i] * filter[len + k - i]) >> 15;
45 
46  for (k = i; k < len; k++)
47  fc_out[k] += (fc_in[i] * filter[ k - i]) >> 15;
48  }
49  }
50 }
51 
52 void ff_celp_circ_addf(float *out, const float *in,
53  const float *lagged, int lag, float fac, int n)
54 {
55  int k;
56  for (k = 0; k < lag; k++)
57  out[k] = in[k] + fac * lagged[n + k - lag];
58  for (; k < n; k++)
59  out[k] = in[k] + fac * lagged[ k - lag];
60 }
61 
62 int ff_celp_lp_synthesis_filter(int16_t *out, const int16_t *filter_coeffs,
63  const int16_t *in, int buffer_length,
64  int filter_length, int stop_on_overflow,
65  int shift, int rounder)
66 {
67  int i,n;
68 
69  for (n = 0; n < buffer_length; n++) {
70  int sum = rounder, sum1;
71  for (i = 1; i <= filter_length; i++)
72  sum -= (unsigned)(filter_coeffs[i-1] * out[n-i]);
73 
74  sum1 = ((sum >> 12) + in[n]) >> shift;
75  sum = av_clip_int16(sum1);
76 
77  if (stop_on_overflow && sum != sum1)
78  return 1;
79 
80  out[n] = sum;
81  }
82 
83  return 0;
84 }
85 
86 void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs,
87  const float* in, int buffer_length,
88  int filter_length)
89 {
90  int i,n;
91 
92 #if 0 // Unoptimized code path for improved readability
93  for (n = 0; n < buffer_length; n++) {
94  out[n] = in[n];
95  for (i = 1; i <= filter_length; i++)
96  out[n] -= filter_coeffs[i-1] * out[n-i];
97  }
98 #else
99  float out0, out1, out2, out3;
100  float old_out0, old_out1, old_out2, old_out3;
101  float a,b,c;
102 
103  a = filter_coeffs[0];
104  b = filter_coeffs[1];
105  c = filter_coeffs[2];
106  b -= filter_coeffs[0] * filter_coeffs[0];
107  c -= filter_coeffs[1] * filter_coeffs[0];
108  c -= filter_coeffs[0] * b;
109 
110  av_assert2((filter_length&1)==0 && filter_length>=4);
111 
112  old_out0 = out[-4];
113  old_out1 = out[-3];
114  old_out2 = out[-2];
115  old_out3 = out[-1];
116  for (n = 0; n <= buffer_length - 4; n+=4) {
117  float tmp0,tmp1,tmp2;
118  float val;
119 
120  out0 = in[0];
121  out1 = in[1];
122  out2 = in[2];
123  out3 = in[3];
124 
125  out0 -= filter_coeffs[2] * old_out1;
126  out1 -= filter_coeffs[2] * old_out2;
127  out2 -= filter_coeffs[2] * old_out3;
128 
129  out0 -= filter_coeffs[1] * old_out2;
130  out1 -= filter_coeffs[1] * old_out3;
131 
132  out0 -= filter_coeffs[0] * old_out3;
133 
134  val = filter_coeffs[3];
135 
136  out0 -= val * old_out0;
137  out1 -= val * old_out1;
138  out2 -= val * old_out2;
139  out3 -= val * old_out3;
140 
141  for (i = 5; i < filter_length; i += 2) {
142  old_out3 = out[-i];
143  val = filter_coeffs[i-1];
144 
145  out0 -= val * old_out3;
146  out1 -= val * old_out0;
147  out2 -= val * old_out1;
148  out3 -= val * old_out2;
149 
150  old_out2 = out[-i-1];
151 
152  val = filter_coeffs[i];
153 
154  out0 -= val * old_out2;
155  out1 -= val * old_out3;
156  out2 -= val * old_out0;
157  out3 -= val * old_out1;
158 
159  FFSWAP(float, old_out0, old_out2);
160  old_out1 = old_out3;
161  }
162 
163  tmp0 = out0;
164  tmp1 = out1;
165  tmp2 = out2;
166 
167  out3 -= a * tmp2;
168  out2 -= a * tmp1;
169  out1 -= a * tmp0;
170 
171  out3 -= b * tmp1;
172  out2 -= b * tmp0;
173 
174  out3 -= c * tmp0;
175 
176 
177  out[0] = out0;
178  out[1] = out1;
179  out[2] = out2;
180  out[3] = out3;
181 
182  old_out0 = out0;
183  old_out1 = out1;
184  old_out2 = out2;
185  old_out3 = out3;
186 
187  out += 4;
188  in += 4;
189  }
190 
191  out -= n;
192  in -= n;
193  for (; n < buffer_length; n++) {
194  out[n] = in[n];
195  for (i = 1; i <= filter_length; i++)
196  out[n] -= filter_coeffs[i-1] * out[n-i];
197  }
198 #endif
199 }
200 
201 void ff_celp_lp_zero_synthesis_filterf(float *out, const float *filter_coeffs,
202  const float *in, int buffer_length,
203  int filter_length)
204 {
205  int i,n;
206 
207  for (n = 0; n < buffer_length; n++) {
208  out[n] = in[n];
209  for (i = 1; i <= filter_length; i++)
210  out[n] += filter_coeffs[i-1] * in[n-i];
211  }
212 }
213 
215 {
216  c->celp_lp_synthesis_filterf = ff_celp_lp_synthesis_filterf;
217  c->celp_lp_zero_synthesis_filterf = ff_celp_lp_zero_synthesis_filterf;
218 
219 #if HAVE_MIPSFPU
221 #endif
222 }
out
FILE * out
Definition: movenc.c:55
b
#define b
Definition: input.c:42
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:62
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
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:86
ff_celp_filter_init
void av_cold ff_celp_filter_init(CELPFContext *c)
Initialize CELPFContext.
Definition: celp_filters.c:214
val
static double val(void *priv, double ch)
Definition: aeval.c:77
avassert.h
av_cold
#define av_cold
Definition: attributes.h:90
av_clip_int16
#define av_clip_int16
Definition: common.h:115
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:32
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:261
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
attributes.h
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:68
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
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:201
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:52
ff_celp_filter_init_mips
void ff_celp_filter_init_mips(CELPFContext *c)
Definition: celp_filters_mips.c:285