FFmpeg
ac3dsp.c
Go to the documentation of this file.
1 /*
2  * AC-3 DSP functions
3  * Copyright (c) 2011 Justin Ruggles
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 #include <math.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "config.h"
27 #include "libavutil/attributes.h"
28 #include "libavutil/common.h"
29 #include "libavutil/intmath.h"
30 #include "libavutil/mem_internal.h"
31 
32 #include "ac3defs.h"
33 #include "ac3dsp.h"
34 #include "ac3tab.h"
35 #include "mathops.h"
36 
37 static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs)
38 {
39  int blk, i;
40 
41  if (!num_reuse_blocks)
42  return;
43 
44  for (i = 0; i < nb_coefs; i++) {
45  uint8_t min_exp = *exp;
46  uint8_t *exp1 = exp + 256;
47  for (blk = 0; blk < num_reuse_blocks; blk++) {
48  uint8_t next_exp = *exp1;
49  if (next_exp < min_exp)
50  min_exp = next_exp;
51  exp1 += 256;
52  }
53  *exp++ = min_exp;
54  }
55 }
56 
57 static void float_to_fixed24_c(int32_t *dst, const float *src, unsigned int len)
58 {
59  const float scale = 1 << 24;
60  do {
61  *dst++ = lrintf(*src++ * scale);
62  *dst++ = lrintf(*src++ * scale);
63  *dst++ = lrintf(*src++ * scale);
64  *dst++ = lrintf(*src++ * scale);
65  *dst++ = lrintf(*src++ * scale);
66  *dst++ = lrintf(*src++ * scale);
67  *dst++ = lrintf(*src++ * scale);
68  *dst++ = lrintf(*src++ * scale);
69  len -= 8;
70  } while (len > 0);
71 }
72 
73 static void ac3_bit_alloc_calc_bap_c(int16_t *mask, int16_t *psd,
74  int start, int end,
75  int snr_offset, int floor,
76  const uint8_t *bap_tab, uint8_t *bap)
77 {
78  int bin, band, band_end;
79 
80  /* special case, if snr offset is -960, set all bap's to zero */
81  if (snr_offset == -960) {
82  memset(bap, 0, AC3_MAX_COEFS);
83  return;
84  }
85 
86  bin = start;
87  band = ff_ac3_bin_to_band_tab[start];
88  do {
89  int m = (FFMAX(mask[band] - snr_offset - floor, 0) & 0x1FE0) + floor;
90  band_end = ff_ac3_band_start_tab[++band];
91  band_end = FFMIN(band_end, end);
92 
93  for (; bin < band_end; bin++) {
94  int address = av_clip_uintp2((psd[bin] - m) >> 5, 6);
95  bap[bin] = bap_tab[address];
96  }
97  } while (end > band_end);
98 }
99 
100 static void ac3_update_bap_counts_c(uint16_t mant_cnt[16], uint8_t *bap,
101  int len)
102 {
103  while (len-- > 0)
104  mant_cnt[bap[len]]++;
105 }
106 
107 DECLARE_ALIGNED(16, const uint16_t, ff_ac3_bap_bits)[16] = {
108  0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16
109 };
110 
111 static int ac3_compute_mantissa_size_c(uint16_t mant_cnt[6][16])
112 {
113  int blk, bap;
114  int bits = 0;
115 
116  for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
117  // bap=1 : 3 mantissas in 5 bits
118  bits += (mant_cnt[blk][1] / 3) * 5;
119  // bap=2 : 3 mantissas in 7 bits
120  // bap=4 : 2 mantissas in 7 bits
121  bits += ((mant_cnt[blk][2] / 3) + (mant_cnt[blk][4] >> 1)) * 7;
122  // bap=3 : 1 mantissa in 3 bits
123  bits += mant_cnt[blk][3] * 3;
124  // bap=5 to 15 : get bits per mantissa from table
125  for (bap = 5; bap < 16; bap++)
126  bits += mant_cnt[blk][bap] * ff_ac3_bap_bits[bap];
127  }
128  return bits;
129 }
130 
131 static void ac3_extract_exponents_c(uint8_t *exp, int32_t *coef, int nb_coefs)
132 {
133  int i;
134 
135  for (i = 0; i < nb_coefs; i++) {
136  int v = abs(coef[i]);
137  exp[i] = v ? 23 - av_log2(v) : 24;
138  }
139 }
140 
141 static void ac3_sum_square_butterfly_int32_c(int64_t sum[4],
142  const int32_t *coef0,
143  const int32_t *coef1,
144  int len)
145 {
146  int i;
147 
148  sum[0] = sum[1] = sum[2] = sum[3] = 0;
149 
150  for (i = 0; i < len; i++) {
151  int lt = coef0[i];
152  int rt = coef1[i];
153  int md = lt + rt;
154  int sd = lt - rt;
155  MAC64(sum[0], lt, lt);
156  MAC64(sum[1], rt, rt);
157  MAC64(sum[2], md, md);
158  MAC64(sum[3], sd, sd);
159  }
160 }
161 
162 static void ac3_sum_square_butterfly_float_c(float sum[4],
163  const float *coef0,
164  const float *coef1,
165  int len)
166 {
167  int i;
168 
169  sum[0] = sum[1] = sum[2] = sum[3] = 0;
170 
171  for (i = 0; i < len; i++) {
172  float lt = coef0[i];
173  float rt = coef1[i];
174  float md = lt + rt;
175  float sd = lt - rt;
176  sum[0] += lt * lt;
177  sum[1] += rt * rt;
178  sum[2] += md * md;
179  sum[3] += sd * sd;
180  }
181 }
182 
183 static void ac3_downmix_5_to_2_symmetric_c(float **samples, float **matrix,
184  int len)
185 {
186  int i;
187  float v0, v1;
188  float front_mix = matrix[0][0];
189  float center_mix = matrix[0][1];
190  float surround_mix = matrix[0][3];
191 
192  for (i = 0; i < len; i++) {
193  v0 = samples[0][i] * front_mix +
194  samples[1][i] * center_mix +
195  samples[3][i] * surround_mix;
196 
197  v1 = samples[1][i] * center_mix +
198  samples[2][i] * front_mix +
199  samples[4][i] * surround_mix;
200 
201  samples[0][i] = v0;
202  samples[1][i] = v1;
203  }
204 }
205 
206 static void ac3_downmix_5_to_1_symmetric_c(float **samples, float **matrix,
207  int len)
208 {
209  int i;
210  float front_mix = matrix[0][0];
211  float center_mix = matrix[0][1];
212  float surround_mix = matrix[0][3];
213 
214  for (i = 0; i < len; i++) {
215  samples[0][i] = samples[0][i] * front_mix +
216  samples[1][i] * center_mix +
217  samples[2][i] * front_mix +
218  samples[3][i] * surround_mix +
219  samples[4][i] * surround_mix;
220  }
221 }
222 
223 static void ac3_downmix_c(float **samples, float **matrix,
224  int out_ch, int in_ch, int len)
225 {
226  int i, j;
227  float v0, v1;
228 
229  if (out_ch == 2) {
230  for (i = 0; i < len; i++) {
231  v0 = v1 = 0.0f;
232  for (j = 0; j < in_ch; j++) {
233  v0 += samples[j][i] * matrix[0][j];
234  v1 += samples[j][i] * matrix[1][j];
235  }
236  samples[0][i] = v0;
237  samples[1][i] = v1;
238  }
239  } else if (out_ch == 1) {
240  for (i = 0; i < len; i++) {
241  v0 = 0.0f;
242  for (j = 0; j < in_ch; j++)
243  v0 += samples[j][i] * matrix[0][j];
244  samples[0][i] = v0;
245  }
246  }
247 }
248 
250  int len)
251 {
252  int i;
253  int64_t v0, v1;
254  int16_t front_mix = matrix[0][0];
255  int16_t center_mix = matrix[0][1];
256  int16_t surround_mix = matrix[0][3];
257 
258  for (i = 0; i < len; i++) {
259  v0 = (int64_t)samples[0][i] * front_mix +
260  (int64_t)samples[1][i] * center_mix +
261  (int64_t)samples[3][i] * surround_mix;
262 
263  v1 = (int64_t)samples[1][i] * center_mix +
264  (int64_t)samples[2][i] * front_mix +
265  (int64_t)samples[4][i] * surround_mix;
266 
267  samples[0][i] = (v0+2048)>>12;
268  samples[1][i] = (v1+2048)>>12;
269  }
270 }
271 
273  int len)
274 {
275  int i;
276  int64_t v0;
277  int16_t front_mix = matrix[0][0];
278  int16_t center_mix = matrix[0][1];
279  int16_t surround_mix = matrix[0][3];
280 
281  for (i = 0; i < len; i++) {
282  v0 = (int64_t)samples[0][i] * front_mix +
283  (int64_t)samples[1][i] * center_mix +
284  (int64_t)samples[2][i] * front_mix +
285  (int64_t)samples[3][i] * surround_mix +
286  (int64_t)samples[4][i] * surround_mix;
287 
288  samples[0][i] = (v0+2048)>>12;
289  }
290 }
291 
292 static void ac3_downmix_c_fixed(int32_t **samples, int16_t **matrix,
293  int out_ch, int in_ch, int len)
294 {
295  int i, j;
296  int64_t v0, v1;
297  if (out_ch == 2) {
298  for (i = 0; i < len; i++) {
299  v0 = v1 = 0;
300  for (j = 0; j < in_ch; j++) {
301  v0 += (int64_t)samples[j][i] * matrix[0][j];
302  v1 += (int64_t)samples[j][i] * matrix[1][j];
303  }
304  samples[0][i] = (v0+2048)>>12;
305  samples[1][i] = (v1+2048)>>12;
306  }
307  } else if (out_ch == 1) {
308  for (i = 0; i < len; i++) {
309  v0 = 0;
310  for (j = 0; j < in_ch; j++)
311  v0 += (int64_t)samples[j][i] * matrix[0][j];
312  samples[0][i] = (v0+2048)>>12;
313  }
314  }
315 }
316 
318  int out_ch, int in_ch, int len)
319 {
320  if (c->in_channels != in_ch || c->out_channels != out_ch) {
321  c->in_channels = in_ch;
322  c->out_channels = out_ch;
323  c->downmix_fixed = NULL;
324 
325  if (in_ch == 5 && out_ch == 2 &&
326  !(matrix[1][0] | matrix[0][2] |
327  matrix[1][3] | matrix[0][4] |
328  (matrix[0][1] ^ matrix[1][1]) |
329  (matrix[0][0] ^ matrix[1][2]))) {
330  c->downmix_fixed = ac3_downmix_5_to_2_symmetric_c_fixed;
331  } else if (in_ch == 5 && out_ch == 1 &&
332  matrix[0][0] == matrix[0][2] &&
333  matrix[0][3] == matrix[0][4]) {
334  c->downmix_fixed = ac3_downmix_5_to_1_symmetric_c_fixed;
335  }
336  }
337 
338  if (c->downmix_fixed)
339  c->downmix_fixed(samples, matrix, len);
340  else
341  ac3_downmix_c_fixed(samples, matrix, out_ch, in_ch, len);
342 }
343 
345  int out_ch, int in_ch, int len)
346 {
347  if (c->in_channels != in_ch || c->out_channels != out_ch) {
348  int **matrix_cmp = (int **)matrix;
349 
350  c->in_channels = in_ch;
351  c->out_channels = out_ch;
352  c->downmix = NULL;
353 
354  if (in_ch == 5 && out_ch == 2 &&
355  !(matrix_cmp[1][0] | matrix_cmp[0][2] |
356  matrix_cmp[1][3] | matrix_cmp[0][4] |
357  (matrix_cmp[0][1] ^ matrix_cmp[1][1]) |
358  (matrix_cmp[0][0] ^ matrix_cmp[1][2]))) {
360  } else if (in_ch == 5 && out_ch == 1 &&
361  matrix_cmp[0][0] == matrix_cmp[0][2] &&
362  matrix_cmp[0][3] == matrix_cmp[0][4]) {
364  }
365 
366 #if ARCH_X86
368 #endif
369  }
370 
371  if (c->downmix)
372  c->downmix(samples, matrix, len);
373  else
374  ac3_downmix_c(samples, matrix, out_ch, in_ch, len);
375 }
376 
378 {
379  c->ac3_exponent_min = ac3_exponent_min_c;
380  c->float_to_fixed24 = float_to_fixed24_c;
381  c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_c;
382  c->update_bap_counts = ac3_update_bap_counts_c;
383  c->compute_mantissa_size = ac3_compute_mantissa_size_c;
384  c->extract_exponents = ac3_extract_exponents_c;
385  c->sum_square_butterfly_int32 = ac3_sum_square_butterfly_int32_c;
386  c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_c;
387  c->in_channels = 0;
388  c->out_channels = 0;
389  c->downmix = NULL;
390  c->downmix_fixed = NULL;
391 
392 #if ARCH_ARM
394 #elif ARCH_X86
396 #elif ARCH_MIPS
398 #endif
399 }
nb_coefs
static int nb_coefs(int length, int level, uint64_t sn)
Definition: af_afwtdn.c:515
mem_internal.h
ac3_compute_mantissa_size_c
static int ac3_compute_mantissa_size_c(uint16_t mant_cnt[6][16])
Definition: ac3dsp.c:111
ff_ac3_bin_to_band_tab
const uint8_t ff_ac3_bin_to_band_tab[253]
Map each frequency coefficient bin to the critical band that contains it.
Definition: ac3.c:47
av_clip_uintp2
#define av_clip_uintp2
Definition: common.h:119
matrix
Definition: vc1dsp.c:42
md
#define md
Definition: vf_colormatrix.c:103
AC3DSPContext
Definition: ac3dsp.h:33
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
ac3_sum_square_butterfly_float_c
static void ac3_sum_square_butterfly_float_c(float sum[4], const float *coef0, const float *coef1, int len)
Definition: ac3dsp.c:162
v0
#define v0
Definition: regdef.h:26
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1389
ac3_downmix_c
static void ac3_downmix_c(float **samples, float **matrix, int out_ch, int in_ch, int len)
Definition: ac3dsp.c:223
ac3_update_bap_counts_c
static void ac3_update_bap_counts_c(uint16_t mant_cnt[16], uint8_t *bap, int len)
Definition: ac3dsp.c:100
av_cold
#define av_cold
Definition: attributes.h:90
ff_ac3dsp_set_downmix_x86
void ff_ac3dsp_set_downmix_x86(AC3DSPContext *c)
Definition: ac3dsp_init.c:69
mask
static const uint16_t mask[17]
Definition: lzw.c:38
floor
static __device__ float floor(float a)
Definition: cuda_runtime.h:173
AC3_MAX_COEFS
#define AC3_MAX_COEFS
Definition: ac3defs.h:29
bits
uint8_t bits
Definition: vp3data.h:141
blk
#define blk(i)
Definition: sha.c:186
ff_ac3_band_start_tab
const uint8_t ff_ac3_band_start_tab[AC3_CRITICAL_BANDS+1]
Starting frequency coefficient bin for each critical band.
Definition: ac3.c:36
ff_ac3dsp_init
av_cold void ff_ac3dsp_init(AC3DSPContext *c)
Definition: ac3dsp.c:377
ac3defs.h
bap_tab
static const uint8_t bap_tab[64]
Definition: dolby_e.c:598
NULL
#define NULL
Definition: coverity.c:32
mathops.h
ac3dsp.h
ff_ac3_bap_bits
const uint16_t ff_ac3_bap_bits[16]
Number of mantissa bits written for each bap value.
Definition: ac3dsp.c:107
ac3_extract_exponents_c
static void ac3_extract_exponents_c(uint8_t *exp, int32_t *coef, int nb_coefs)
Definition: ac3dsp.c:131
abs
#define abs(x)
Definition: cuda_runtime.h:35
exp
int8_t exp
Definition: eval.c:72
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
ac3_downmix_5_to_1_symmetric_c_fixed
static void ac3_downmix_5_to_1_symmetric_c_fixed(int32_t **samples, int16_t **matrix, int len)
Definition: ac3dsp.c:272
float_to_fixed24_c
static void float_to_fixed24_c(int32_t *dst, const float *src, unsigned int len)
Definition: ac3dsp.c:57
ff_ac3dsp_init_arm
void ff_ac3dsp_init_arm(AC3DSPContext *c)
Definition: ac3dsp_init_arm.c:47
attributes.h
ac3_downmix_5_to_2_symmetric_c
static void ac3_downmix_5_to_2_symmetric_c(float **samples, float **matrix, int len)
Definition: ac3dsp.c:183
ac3_sum_square_butterfly_int32_c
static void ac3_sum_square_butterfly_int32_c(int64_t sum[4], const int32_t *coef0, const int32_t *coef1, int len)
Definition: ac3dsp.c:141
ac3_bit_alloc_calc_bap_c
static void ac3_bit_alloc_calc_bap_c(int16_t *mask, int16_t *psd, int start, int end, int snr_offset, int floor, const uint8_t *bap_tab, uint8_t *bap)
Definition: ac3dsp.c:73
DECLARE_ALIGNED
#define DECLARE_ALIGNED(n, t, v)
Definition: mem.h:116
lrintf
#define lrintf(x)
Definition: libm_mips.h:72
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
ac3_downmix_5_to_2_symmetric_c_fixed
static void ac3_downmix_5_to_2_symmetric_c_fixed(int32_t **samples, int16_t **matrix, int len)
Definition: ac3dsp.c:249
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AC3_MAX_BLOCKS
#define AC3_MAX_BLOCKS
Definition: ac3defs.h:31
len
int len
Definition: vorbis_enc_data.h:426
ff_ac3dsp_downmix
void ff_ac3dsp_downmix(AC3DSPContext *c, float **samples, float **matrix, int out_ch, int in_ch, int len)
Definition: ac3dsp.c:344
ff_ac3dsp_downmix_fixed
void ff_ac3dsp_downmix_fixed(AC3DSPContext *c, int32_t **samples, int16_t **matrix, int out_ch, int in_ch, int len)
Definition: ac3dsp.c:317
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
MAC64
#define MAC64(d, a, b)
Definition: mathops.h:75
ff_ac3dsp_init_x86
void ff_ac3dsp_init_x86(AC3DSPContext *c)
Definition: ac3dsp_init.c:36
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
ac3_downmix_5_to_1_symmetric_c
static void ac3_downmix_5_to_1_symmetric_c(float **samples, float **matrix, int len)
Definition: ac3dsp.c:206
ff_ac3dsp_init_mips
void ff_ac3dsp_init_mips(AC3DSPContext *c)
Definition: ac3dsp_mips.c:404
int32_t
int32_t
Definition: audioconvert.c:56
ac3_exponent_min_c
static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs)
Definition: ac3dsp.c:37
ac3tab.h
ac3_downmix_c_fixed
static void ac3_downmix_c_fixed(int32_t **samples, int16_t **matrix, int out_ch, int in_ch, int len)
Definition: ac3dsp.c:292
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
intmath.h