2 * AC-3 encoder float/fixed template
3 * Copyright (c) 2000 Fabrice Bellard
4 * Copyright (c) 2006-2011 Justin Ruggles <justin.ruggles@gmail.com>
5 * Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de>
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 * AC-3 encoder float/fixed template
29 #include "config_components.h"
33 #include "libavutil/attributes.h"
34 #include "libavutil/avassert.h"
35 #include "libavutil/mem_internal.h"
42 #define RENAME(element) element ## _float
44 #define RENAME(element) element ## _fixed
48 * Apply the MDCT to input samples to generate frequency coefficients.
49 * This applies the KBD window and normalizes the input to reduce precision
50 * loss due to fixed-point calculations.
52 static void apply_mdct(AC3EncodeContext
*s
, uint8_t * const *samples
)
54 av_assert1(s
->num_blocks
> 0);
56 for (int ch
= 0; ch
< s
->channels
; ch
++) {
57 const SampleType
*input_samples0
= (const SampleType
*)s
->planar_samples
[ch
];
58 /* Reorder channels from native order to AC-3 order. */
59 const SampleType
*input_samples1
= (const SampleType
*)samples
[s
->channel_map
[ch
]];
63 AC3Block
*block
= &s
->blocks
[blk
];
64 SampleType
*windowed_samples
= s
->RENAME(windowed_samples
);
66 s
->fdsp
->vector_fmul(windowed_samples
, input_samples0
,
67 s
->RENAME(mdct_window
), AC3_BLOCK_SIZE
);
68 s
->fdsp
->vector_fmul_reverse(windowed_samples
+ AC3_BLOCK_SIZE
,
70 s
->RENAME(mdct_window
), AC3_BLOCK_SIZE
);
72 s
->tx_fn(s
->tx
, block
->mdct_coef
[ch
+1],
73 windowed_samples
, sizeof(*windowed_samples
));
74 input_samples0
= input_samples1
;
75 input_samples1
+= AC3_BLOCK_SIZE
;
76 } while (++blk
< s
->num_blocks
);
78 /* Store last 256 samples of current frame */
79 memcpy(s
->planar_samples
[ch
], input_samples0
,
80 AC3_BLOCK_SIZE
* sizeof(*input_samples0
));
86 * Calculate coupling channel and coupling coordinates.
88 static void apply_channel_coupling(AC3EncodeContext
*s
)
90 LOCAL_ALIGNED_32(CoefType
, cpl_coords
, [AC3_MAX_BLOCKS
], [AC3_MAX_CHANNELS
][16]);
92 LOCAL_ALIGNED_32(int32_t, fixed_cpl_coords
, [AC3_MAX_BLOCKS
], [AC3_MAX_CHANNELS
][16]);
94 int32_t (*fixed_cpl_coords
)[AC3_MAX_CHANNELS
][16] = cpl_coords
;
96 int av_uninit(blk
), ch
, bnd
, i
, j
;
97 CoefSumType energy
[AC3_MAX_BLOCKS
][AC3_MAX_CHANNELS
][16] = {{{0}}};
98 int cpl_start
, num_cpl_coefs
;
100 memset(cpl_coords
, 0, AC3_MAX_BLOCKS
* sizeof(*cpl_coords
));
102 memset(fixed_cpl_coords
, 0, AC3_MAX_BLOCKS
* sizeof(*cpl_coords
));
105 /* align start to 16-byte boundary. align length to multiple of 32.
106 note: coupling start bin % 4 will always be 1 */
107 cpl_start
= s
->start_freq
[CPL_CH
] - 1;
108 num_cpl_coefs
= FFALIGN(s
->num_cpl_subbands
* 12 + 1, 32);
109 cpl_start
= FFMIN(256, cpl_start
+ num_cpl_coefs
) - num_cpl_coefs
;
111 /* calculate coupling channel from fbw channels */
112 for (blk
= 0; blk
< s
->num_blocks
; blk
++) {
113 AC3Block
*block
= &s
->blocks
[blk
];
114 CoefType
*cpl_coef
= &block
->mdct_coef
[CPL_CH
][cpl_start
];
115 if (!block
->cpl_in_use
)
117 memset(cpl_coef
, 0, num_cpl_coefs
* sizeof(*cpl_coef
));
118 for (ch
= 1; ch
<= s
->fbw_channels
; ch
++) {
119 CoefType
*ch_coef
= &block
->mdct_coef
[ch
][cpl_start
];
120 if (!block
->channel_in_cpl
[ch
])
122 for (i
= 0; i
< num_cpl_coefs
; i
++)
123 cpl_coef
[i
] += ch_coef
[i
];
126 /* coefficients must be clipped in order to be encoded */
127 clip_coefficients(&s
->adsp
, cpl_coef
, num_cpl_coefs
);
130 /* calculate energy in each band in coupling channel and each fbw channel */
131 /* TODO: possibly use SIMD to speed up energy calculation */
133 i
= s
->start_freq
[CPL_CH
];
134 while (i
< s
->cpl_end_freq
) {
135 int band_size
= s
->cpl_band_sizes
[bnd
];
136 for (ch
= CPL_CH
; ch
<= s
->fbw_channels
; ch
++) {
137 for (blk
= 0; blk
< s
->num_blocks
; blk
++) {
138 AC3Block
*block
= &s
->blocks
[blk
];
139 if (!block
->cpl_in_use
|| (ch
> CPL_CH
&& !block
->channel_in_cpl
[ch
]))
141 for (j
= 0; j
< band_size
; j
++) {
142 CoefType v
= block
->mdct_coef
[ch
][i
+j
];
143 MAC_COEF(energy
[blk
][ch
][bnd
], v
, v
);
151 /* calculate coupling coordinates for all blocks for all channels */
152 for (blk
= 0; blk
< s
->num_blocks
; blk
++) {
153 AC3Block
*block
= &s
->blocks
[blk
];
154 if (!block
->cpl_in_use
)
156 for (ch
= 1; ch
<= s
->fbw_channels
; ch
++) {
157 if (!block
->channel_in_cpl
[ch
])
159 for (bnd
= 0; bnd
< s
->num_cpl_bands
; bnd
++) {
160 cpl_coords
[blk
][ch
][bnd
] = calc_cpl_coord(energy
[blk
][ch
][bnd
],
161 energy
[blk
][CPL_CH
][bnd
]);
166 /* determine which blocks to send new coupling coordinates for */
167 for (blk
= 0; blk
< s
->num_blocks
; blk
++) {
168 AC3Block
*block
= &s
->blocks
[blk
];
169 AC3Block
*block0
= blk
? &s
->blocks
[blk
-1] : NULL
;
171 memset(block
->new_cpl_coords
, 0, sizeof(block
->new_cpl_coords
));
173 if (block
->cpl_in_use
) {
174 /* send new coordinates if this is the first block, if previous
175 * block did not use coupling but this block does, the channels
176 * using coupling has changed from the previous block, or the
177 * coordinate difference from the last block for any channel is
178 * greater than a threshold value. */
179 if (blk
== 0 || !block0
->cpl_in_use
) {
180 for (ch
= 1; ch
<= s
->fbw_channels
; ch
++)
181 block
->new_cpl_coords
[ch
] = 1;
183 for (ch
= 1; ch
<= s
->fbw_channels
; ch
++) {
184 if (!block
->channel_in_cpl
[ch
])
186 if (!block0
->channel_in_cpl
[ch
]) {
187 block
->new_cpl_coords
[ch
] = 1;
189 CoefSumType coord_diff
= 0;
190 for (bnd
= 0; bnd
< s
->num_cpl_bands
; bnd
++) {
191 coord_diff
+= FFABS(cpl_coords
[blk
-1][ch
][bnd
] -
192 cpl_coords
[blk
][ch
][bnd
]);
194 coord_diff
/= s
->num_cpl_bands
;
195 if (coord_diff
> NEW_CPL_COORD_THRESHOLD
)
196 block
->new_cpl_coords
[ch
] = 1;
203 av_assert1(s
->fbw_channels
> 0);
205 /* calculate final coupling coordinates, taking into account reusing of
206 coordinates in successive blocks */
207 for (bnd
= 0; bnd
< s
->num_cpl_bands
; bnd
++) {
209 while (blk
< s
->num_blocks
) {
211 AC3Block
*block
= &s
->blocks
[blk
];
213 if (!block
->cpl_in_use
) {
218 for (ch
= 1; ch
<= s
->fbw_channels
; ch
++) {
219 CoefSumType energy_ch
, energy_cpl
;
220 if (!block
->channel_in_cpl
[ch
])
222 energy_cpl
= energy
[blk
][CPL_CH
][bnd
];
223 energy_ch
= energy
[blk
][ch
][bnd
];
225 while (blk1
< s
->num_blocks
&& !s
->blocks
[blk1
].new_cpl_coords
[ch
]) {
226 if (s
->blocks
[blk1
].cpl_in_use
) {
227 energy_cpl
+= energy
[blk1
][CPL_CH
][bnd
];
228 energy_ch
+= energy
[blk1
][ch
][bnd
];
232 cpl_coords
[blk
][ch
][bnd
] = calc_cpl_coord(energy_ch
, energy_cpl
);
238 /* calculate exponents/mantissas for coupling coordinates */
239 for (blk
= 0; blk
< s
->num_blocks
; blk
++) {
240 AC3Block
*block
= &s
->blocks
[blk
];
241 if (!block
->cpl_in_use
)
245 s
->ac3dsp
.float_to_fixed24(fixed_cpl_coords
[blk
][1],
247 s
->fbw_channels
* 16);
249 s
->ac3dsp
.extract_exponents(block
->cpl_coord_exp
[1],
250 fixed_cpl_coords
[blk
][1],
251 s
->fbw_channels
* 16);
253 for (ch
= 1; ch
<= s
->fbw_channels
; ch
++) {
254 int bnd
, min_exp
, max_exp
, master_exp
;
256 if (!block
->new_cpl_coords
[ch
])
259 /* determine master exponent */
260 min_exp
= max_exp
= block
->cpl_coord_exp
[ch
][0];
261 for (bnd
= 1; bnd
< s
->num_cpl_bands
; bnd
++) {
262 int exp
= block
->cpl_coord_exp
[ch
][bnd
];
263 min_exp
= FFMIN(exp
, min_exp
);
264 max_exp
= FFMAX(exp
, max_exp
);
266 master_exp
= ((max_exp
- 15) + 2) / 3;
267 master_exp
= FFMAX(master_exp
, 0);
268 while (min_exp
< master_exp
* 3)
270 for (bnd
= 0; bnd
< s
->num_cpl_bands
; bnd
++) {
271 block
->cpl_coord_exp
[ch
][bnd
] = av_clip(block
->cpl_coord_exp
[ch
][bnd
] -
272 master_exp
* 3, 0, 15);
274 block
->cpl_master_exp
[ch
] = master_exp
;
276 /* quantize mantissas */
277 for (bnd
= 0; bnd
< s
->num_cpl_bands
; bnd
++) {
278 int cpl_exp
= block
->cpl_coord_exp
[ch
][bnd
];
279 int cpl_mant
= (fixed_cpl_coords
[blk
][ch
][bnd
] << (5 + cpl_exp
+ master_exp
* 3)) >> 24;
285 block
->cpl_coord_mant
[ch
][bnd
] = cpl_mant
;
290 if (AC3ENC_FLOAT
&& CONFIG_EAC3_ENCODER
&& s
->eac3
)
291 ff_eac3_set_cpl_states(s
);
296 * Determine rematrixing flags for each block and band.
298 static void compute_rematrixing_strategy(AC3EncodeContext
*s
)
302 AC3Block
*block
, *block0
= NULL
;
304 if (s
->channel_mode
!= AC3_CHMODE_STEREO
)
307 for (blk
= 0; blk
< s
->num_blocks
; blk
++) {
308 block
= &s
->blocks
[blk
];
309 block
->new_rematrixing_strategy
= !blk
;
311 block
->num_rematrixing_bands
= 4;
312 if (block
->cpl_in_use
) {
313 block
->num_rematrixing_bands
-= (s
->start_freq
[CPL_CH
] <= 61);
314 block
->num_rematrixing_bands
-= (s
->start_freq
[CPL_CH
] == 37);
315 if (blk
&& block
->num_rematrixing_bands
!= block0
->num_rematrixing_bands
)
316 block
->new_rematrixing_strategy
= 1;
318 nb_coefs
= FFMIN(block
->end_freq
[1], block
->end_freq
[2]);
320 if (!s
->rematrixing_enabled
) {
325 for (bnd
= 0; bnd
< block
->num_rematrixing_bands
; bnd
++) {
326 /* calculate sum of squared coeffs for one band in one block */
327 int start
= ff_ac3_rematrix_band_tab
[bnd
];
328 int end
= FFMIN(nb_coefs
, ff_ac3_rematrix_band_tab
[bnd
+1]);
330 sum_square_butterfly(s
, sum
, block
->mdct_coef
[1] + start
,
331 block
->mdct_coef
[2] + start
, end
- start
);
333 /* compare sums to determine if rematrixing will be used for this band */
334 if (FFMIN(sum
[2], sum
[3]) < FFMIN(sum
[0], sum
[1]))
335 block
->rematrixing_flags
[bnd
] = 1;
337 block
->rematrixing_flags
[bnd
] = 0;
339 /* determine if new rematrixing flags will be sent */
341 block
->rematrixing_flags
[bnd
] != block0
->rematrixing_flags
[bnd
]) {
342 block
->new_rematrixing_strategy
= 1;
350 static void encode_frame(AC3EncodeContext
*s
, uint8_t * const *samples
)
352 apply_mdct(s
, samples
);
354 s
->cpl_on
= s
->cpl_enabled
;
355 ff_ac3_compute_coupling_strategy(s
);
358 apply_channel_coupling(s
);
360 compute_rematrixing_strategy(s
);
363 scale_coefficients(s
);