blob: 2ffe1f8de825c2df14b4abea7740e5df6b5737ac
1 | /* |
2 | * AAC encoder TNS |
3 | * Copyright (C) 2015 Rostislav Pehlivanov |
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 | * AAC encoder temporal noise shaping |
25 | * @author Rostislav Pehlivanov ( atomnuker gmail com ) |
26 | */ |
27 | |
28 | #include "libavutil/libm.h" |
29 | #include "aacenc.h" |
30 | #include "aacenc_tns.h" |
31 | #include "aactab.h" |
32 | #include "aacenc_utils.h" |
33 | #include "aacenc_quantization.h" |
34 | |
35 | /* Could be set to 3 to save an additional bit at the cost of little quality */ |
36 | #define TNS_Q_BITS 4 |
37 | |
38 | /* Coefficient resolution in short windows */ |
39 | #define TNS_Q_BITS_IS8 4 |
40 | |
41 | /* We really need the bits we save here elsewhere */ |
42 | #define TNS_ENABLE_COEF_COMPRESSION |
43 | |
44 | /* TNS will only be used if the LPC gain is within these margins */ |
45 | #define TNS_GAIN_THRESHOLD_LOW 1.4f |
46 | #define TNS_GAIN_THRESHOLD_HIGH 1.16f*TNS_GAIN_THRESHOLD_LOW |
47 | |
48 | static inline int compress_coeffs(int *coef, int order, int c_bits) |
49 | { |
50 | int i; |
51 | const int low_idx = c_bits ? 4 : 2; |
52 | const int shift_val = c_bits ? 8 : 4; |
53 | const int high_idx = c_bits ? 11 : 5; |
54 | #ifndef TNS_ENABLE_COEF_COMPRESSION |
55 | return 0; |
56 | #endif /* TNS_ENABLE_COEF_COMPRESSION */ |
57 | for (i = 0; i < order; i++) |
58 | if (coef[i] >= low_idx && coef[i] <= high_idx) |
59 | return 0; |
60 | for (i = 0; i < order; i++) |
61 | coef[i] -= (coef[i] > high_idx) ? shift_val : 0; |
62 | return 1; |
63 | } |
64 | |
65 | /** |
66 | * Encode TNS data. |
67 | * Coefficient compression is simply not lossless as it should be |
68 | * on any decoder tested and as such is not active. |
69 | */ |
70 | void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce) |
71 | { |
72 | TemporalNoiseShaping *tns = &sce->tns; |
73 | int i, w, filt, coef_compress = 0, coef_len; |
74 | const int is8 = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE; |
75 | const int c_bits = is8 ? TNS_Q_BITS_IS8 == 4 : TNS_Q_BITS == 4; |
76 | |
77 | if (!sce->tns.present) |
78 | return; |
79 | |
80 | for (i = 0; i < sce->ics.num_windows; i++) { |
81 | put_bits(&s->pb, 2 - is8, sce->tns.n_filt[i]); |
82 | if (!tns->n_filt[i]) |
83 | continue; |
84 | put_bits(&s->pb, 1, c_bits); |
85 | for (filt = 0; filt < tns->n_filt[i]; filt++) { |
86 | put_bits(&s->pb, 6 - 2 * is8, tns->length[i][filt]); |
87 | put_bits(&s->pb, 5 - 2 * is8, tns->order[i][filt]); |
88 | if (!tns->order[i][filt]) |
89 | continue; |
90 | put_bits(&s->pb, 1, tns->direction[i][filt]); |
91 | coef_compress = compress_coeffs(tns->coef_idx[i][filt], |
92 | tns->order[i][filt], c_bits); |
93 | put_bits(&s->pb, 1, coef_compress); |
94 | coef_len = c_bits + 3 - coef_compress; |
95 | for (w = 0; w < tns->order[i][filt]; w++) |
96 | put_bits(&s->pb, coef_len, tns->coef_idx[i][filt][w]); |
97 | } |
98 | } |
99 | } |
100 | |
101 | /* Apply TNS filter */ |
102 | void ff_aac_apply_tns(AACEncContext *s, SingleChannelElement *sce) |
103 | { |
104 | TemporalNoiseShaping *tns = &sce->tns; |
105 | IndividualChannelStream *ics = &sce->ics; |
106 | int w, filt, m, i, top, order, bottom, start, end, size, inc; |
107 | const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb); |
108 | float lpc[TNS_MAX_ORDER]; |
109 | |
110 | for (w = 0; w < ics->num_windows; w++) { |
111 | bottom = ics->num_swb; |
112 | for (filt = 0; filt < tns->n_filt[w]; filt++) { |
113 | top = bottom; |
114 | bottom = FFMAX(0, top - tns->length[w][filt]); |
115 | order = tns->order[w][filt]; |
116 | if (order == 0) |
117 | continue; |
118 | |
119 | // tns_decode_coef |
120 | compute_lpc_coefs(tns->coef[w][filt], order, lpc, 0, 0, 0); |
121 | |
122 | start = ics->swb_offset[FFMIN(bottom, mmm)]; |
123 | end = ics->swb_offset[FFMIN( top, mmm)]; |
124 | if ((size = end - start) <= 0) |
125 | continue; |
126 | if (tns->direction[w][filt]) { |
127 | inc = -1; |
128 | start = end - 1; |
129 | } else { |
130 | inc = 1; |
131 | } |
132 | start += w * 128; |
133 | |
134 | /* AR filter */ |
135 | for (m = 0; m < size; m++, start += inc) { |
136 | for (i = 1; i <= FFMIN(m, order); i++) { |
137 | sce->coeffs[start] += lpc[i-1]*sce->pcoeffs[start - i*inc]; |
138 | } |
139 | } |
140 | } |
141 | } |
142 | } |
143 | |
144 | /* |
145 | * c_bits - 1 if 4 bit coefficients, 0 if 3 bit coefficients |
146 | */ |
147 | static inline void quantize_coefs(double *coef, int *idx, float *lpc, int order, |
148 | int c_bits) |
149 | { |
150 | int i; |
151 | const float *quant_arr = tns_tmp2_map[c_bits]; |
152 | for (i = 0; i < order; i++) { |
153 | idx[i] = quant_array_idx(coef[i], quant_arr, c_bits ? 16 : 8); |
154 | lpc[i] = quant_arr[idx[i]]; |
155 | } |
156 | } |
157 | |
158 | /* |
159 | * 3 bits per coefficient with 8 short windows |
160 | */ |
161 | void ff_aac_search_for_tns(AACEncContext *s, SingleChannelElement *sce) |
162 | { |
163 | TemporalNoiseShaping *tns = &sce->tns; |
164 | int w, g, count = 0; |
165 | double gain, coefs[MAX_LPC_ORDER]; |
166 | const int mmm = FFMIN(sce->ics.tns_max_bands, sce->ics.max_sfb); |
167 | const int is8 = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE; |
168 | const int c_bits = is8 ? TNS_Q_BITS_IS8 == 4 : TNS_Q_BITS == 4; |
169 | const int sfb_start = av_clip(tns_min_sfb[is8][s->samplerate_index], 0, mmm); |
170 | const int sfb_end = av_clip(sce->ics.num_swb, 0, mmm); |
171 | const int order = is8 ? 7 : s->profile == FF_PROFILE_AAC_LOW ? 12 : TNS_MAX_ORDER; |
172 | const int slant = sce->ics.window_sequence[0] == LONG_STOP_SEQUENCE ? 1 : |
173 | sce->ics.window_sequence[0] == LONG_START_SEQUENCE ? 0 : 2; |
174 | const int sfb_len = sfb_end - sfb_start; |
175 | const int coef_len = sce->ics.swb_offset[sfb_end] - sce->ics.swb_offset[sfb_start]; |
176 | |
177 | if (coef_len <= 0 || sfb_len <= 0) { |
178 | sce->tns.present = 0; |
179 | return; |
180 | } |
181 | |
182 | for (w = 0; w < sce->ics.num_windows; w++) { |
183 | float en[2] = {0.0f, 0.0f}; |
184 | int oc_start = 0, os_start = 0; |
185 | int coef_start = sce->ics.swb_offset[sfb_start]; |
186 | |
187 | for (g = sfb_start; g < sce->ics.num_swb && g <= sfb_end; g++) { |
188 | FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[w*16+g]; |
189 | if (g > sfb_start + (sfb_len/2)) |
190 | en[1] += band->energy; |
191 | else |
192 | en[0] += band->energy; |
193 | } |
194 | |
195 | /* LPC */ |
196 | gain = ff_lpc_calc_ref_coefs_f(&s->lpc, &sce->coeffs[w*128 + coef_start], |
197 | coef_len, order, coefs); |
198 | |
199 | if (!order || !isfinite(gain) || gain < TNS_GAIN_THRESHOLD_LOW || gain > TNS_GAIN_THRESHOLD_HIGH) |
200 | continue; |
201 | |
202 | tns->n_filt[w] = is8 ? 1 : order != TNS_MAX_ORDER ? 2 : 3; |
203 | for (g = 0; g < tns->n_filt[w]; g++) { |
204 | tns->direction[w][g] = slant != 2 ? slant : en[g] < en[!g]; |
205 | tns->order[w][g] = g < tns->n_filt[w] ? order/tns->n_filt[w] : order - oc_start; |
206 | tns->length[w][g] = g < tns->n_filt[w] ? sfb_len/tns->n_filt[w] : sfb_len - os_start; |
207 | quantize_coefs(&coefs[oc_start], tns->coef_idx[w][g], tns->coef[w][g], |
208 | tns->order[w][g], c_bits); |
209 | oc_start += tns->order[w][g]; |
210 | os_start += tns->length[w][g]; |
211 | } |
212 | count++; |
213 | } |
214 | sce->tns.present = !!count; |
215 | } |
216 |