1 /******************************************************************************
2 * *
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include <stdlib.h>
21 #include <math.h>
22 #include "ixheaacd_type_def.h"
23 #include "ixheaacd_cnst.h"
24 #include "ixheaacd_peak_limiter_struct_def.h"
25 #include "ixheaacd_constants.h"
26 #include "ixheaacd_basic_ops32.h"
27 #include "ixheaacd_basic_ops16.h"
28
29 #define MAX(x, y) ((x) > (y) ? (x) : (y))
30 #define MIN(x, y) ((x) > (y) ? (y) : (x))
31
32 /**
33 * ixheaacd_peak_limiter_init
34 *
35 * \brief Peak Limiter initialization
36 *
37 * \param [in/out] peak_limiter Pointer to peak_limiter struct
38 * \param [in] num_channels Number of ouptut channels
39 * \param [in] sample_rate Sampling rate value
40 * \param [in] buffer Peak limiter buffer of size PEAK_LIM_BUFFER_SIZE
41 *
42 * \return WORD32
43 *
44 */
ixheaacd_peak_limiter_init(ia_peak_limiter_struct * peak_limiter,UWORD32 num_channels,UWORD32 sample_rate,FLOAT32 * buffer,UWORD32 * delay_in_samples)45 WORD32 ixheaacd_peak_limiter_init(ia_peak_limiter_struct *peak_limiter,
46 UWORD32 num_channels, UWORD32 sample_rate,
47 FLOAT32 *buffer, UWORD32 *delay_in_samples) {
48 UWORD32 attack;
49
50 attack = (UWORD32)(DEFAULT_ATTACK_TIME_MS * sample_rate / 1000);
51 *delay_in_samples = attack;
52
53 if (attack < 1) return 0;
54
55 peak_limiter->max_buf = buffer;
56 peak_limiter->max_idx = 0;
57 peak_limiter->cir_buf_pnt = 0;
58 peak_limiter->delayed_input = buffer + attack * 4 + 32;
59
60 peak_limiter->delayed_input_index = 0;
61 peak_limiter->attack_time = DEFAULT_ATTACK_TIME_MS;
62 peak_limiter->release_time = DEFAULT_RELEASE_TIME_MS;
63 peak_limiter->attack_time_samples = attack;
64 peak_limiter->attack_constant = (FLOAT32)pow(0.1, 1.0 / (attack + 1));
65 peak_limiter->release_constant = (FLOAT32)pow(
66 0.1, 1.0 / (DEFAULT_RELEASE_TIME_MS * sample_rate / 1000 + 1));
67 peak_limiter->num_channels = num_channels;
68 peak_limiter->sample_rate = sample_rate;
69 peak_limiter->min_gain = 1.0f;
70 peak_limiter->limiter_on = 1;
71 peak_limiter->pre_smoothed_gain = 1.0f;
72 peak_limiter->gain_modified = 1.0f;
73
74 return 0;
75 }
ixheaacd_peak_limiter_process_float(ia_peak_limiter_struct * peak_limiter,FLOAT32 samples[MAX_NUM_CHANNELS][4096],UWORD32 frame_len)76 VOID ixheaacd_peak_limiter_process_float(ia_peak_limiter_struct *peak_limiter,
77 FLOAT32 samples[MAX_NUM_CHANNELS][4096],
78 UWORD32 frame_len) {
79 UWORD32 i, j;
80 FLOAT32 tmp, gain;
81 FLOAT32 min_gain = 1.0f;
82 FLOAT32 maximum;
83 UWORD32 num_channels = peak_limiter->num_channels;
84 UWORD32 attack_time_samples = peak_limiter->attack_time_samples;
85 FLOAT32 attack_constant = peak_limiter->attack_constant;
86 FLOAT32 release_constant = peak_limiter->release_constant;
87 FLOAT32 *max_buf = peak_limiter->max_buf;
88 FLOAT32 gain_modified = peak_limiter->gain_modified;
89 FLOAT32 *delayed_input = peak_limiter->delayed_input;
90 UWORD32 delayed_input_index = peak_limiter->delayed_input_index;
91 FLOAT64 pre_smoothed_gain = peak_limiter->pre_smoothed_gain;
92 FLOAT32 limit_threshold = PEAK_LIM_THR_FLOAT;
93
94 if (peak_limiter->limiter_on || (FLOAT32)pre_smoothed_gain) {
95 for (i = 0; i < frame_len; i++) {
96 tmp = 0.0f;
97 for (j = 0; j < num_channels; j++) {
98 tmp = (FLOAT32)MAX(tmp, fabs(samples[j][i]));
99 }
100 max_buf[peak_limiter->cir_buf_pnt] = tmp;
101
102 if (peak_limiter->max_idx == peak_limiter->cir_buf_pnt) {
103 peak_limiter->max_idx = 0;
104 for (j = 1; j < (attack_time_samples); j++) {
105 if (max_buf[j] > max_buf[peak_limiter->max_idx]) peak_limiter->max_idx = j;
106 }
107 } else if (tmp >= max_buf[peak_limiter->max_idx]) {
108 peak_limiter->max_idx = peak_limiter->cir_buf_pnt;
109 }
110
111 peak_limiter->cir_buf_pnt++;
112
113 if (peak_limiter->cir_buf_pnt == (WORD32)(attack_time_samples))
114 peak_limiter->cir_buf_pnt = 0;
115 maximum = max_buf[peak_limiter->max_idx];
116
117 if (maximum > limit_threshold) {
118 gain = limit_threshold / maximum;
119 } else {
120 gain = 1;
121 }
122
123 if (gain < pre_smoothed_gain) {
124 gain_modified =
125 MIN(gain_modified, (gain - 0.1f * (FLOAT32)pre_smoothed_gain) * 1.11111111f);
126 } else {
127 gain_modified = gain;
128 }
129
130 if (gain_modified < pre_smoothed_gain) {
131 pre_smoothed_gain = attack_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
132 pre_smoothed_gain = MAX(pre_smoothed_gain, gain);
133 } else {
134 pre_smoothed_gain =
135 release_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
136 }
137
138 gain = (FLOAT32)pre_smoothed_gain;
139
140 for (j = 0; j < num_channels; j++) {
141 tmp = delayed_input[delayed_input_index * num_channels + j];
142 delayed_input[delayed_input_index * num_channels + j] = samples[j][i];
143
144 tmp *= gain;
145
146 if (tmp > limit_threshold)
147 tmp = limit_threshold;
148 else if (tmp < -limit_threshold)
149 tmp = -limit_threshold;
150
151 samples[j][i] = tmp;
152 }
153
154 delayed_input_index++;
155 if (delayed_input_index >= attack_time_samples) delayed_input_index = 0;
156
157 if (gain < min_gain) min_gain = gain;
158 }
159 } else {
160 for (i = 0; i < frame_len; i++) {
161 for (j = 0; j < num_channels; j++) {
162 tmp = delayed_input[delayed_input_index * num_channels + j];
163 delayed_input[delayed_input_index * num_channels + j] = samples[j][i];
164 samples[j][i] = tmp;
165 }
166
167 delayed_input_index++;
168 if (delayed_input_index >= attack_time_samples) delayed_input_index = 0;
169 }
170 }
171
172 peak_limiter->gain_modified = gain_modified;
173 peak_limiter->delayed_input_index = delayed_input_index;
174 peak_limiter->pre_smoothed_gain = pre_smoothed_gain;
175 peak_limiter->min_gain = min_gain;
176
177 return;
178 }
179
180 /**
181 * ixheaacd_peak_limiter_process
182 *
183 * \brief Peak Limiter process
184 *
185 * \param [in/out] peak_limiter
186 * \param [in] samples
187 * \param [in] frame_len
188 *
189 * \return WORD32
190 *
191 */
ixheaacd_peak_limiter_process(ia_peak_limiter_struct * peak_limiter,VOID * samples_t,UWORD32 frame_len,UWORD8 * qshift_adj)192 VOID ixheaacd_peak_limiter_process(ia_peak_limiter_struct *peak_limiter,
193 VOID *samples_t, UWORD32 frame_len,
194 UWORD8 *qshift_adj) {
195 UWORD32 i, j;
196 FLOAT32 tmp, gain;
197 FLOAT32 min_gain = 1.0f;
198 FLOAT32 maximum;
199 UWORD32 num_channels = peak_limiter->num_channels;
200 UWORD32 attack_time_samples = peak_limiter->attack_time_samples;
201 FLOAT32 attack_constant = peak_limiter->attack_constant;
202 FLOAT32 release_constant = peak_limiter->release_constant;
203 FLOAT32 *max_buf = peak_limiter->max_buf;
204 FLOAT32 gain_modified = peak_limiter->gain_modified;
205 FLOAT32 *delayed_input = peak_limiter->delayed_input;
206 UWORD32 delayed_input_index = peak_limiter->delayed_input_index;
207 FLOAT64 pre_smoothed_gain = peak_limiter->pre_smoothed_gain;
208 WORD32 limit_threshold = PEAK_LIM_THR_FIX;
209
210 WORD32 *samples = (WORD32 *)samples_t;
211
212 if (peak_limiter->limiter_on || (FLOAT32)pre_smoothed_gain) {
213 for (i = 0; i < frame_len; i++) {
214 tmp = 0.0f;
215 for (j = 0; j < num_channels; j++) {
216 FLOAT32 gain_t = (FLOAT32)(1 << *(qshift_adj + j));
217 tmp = (FLOAT32)MAX(tmp, fabs((samples[i * num_channels + j] * gain_t)));
218 }
219 max_buf[peak_limiter->cir_buf_pnt] = tmp;
220
221 if (peak_limiter->max_idx == peak_limiter->cir_buf_pnt) {
222 peak_limiter->max_idx = 0;
223 for (j = 1; j < (attack_time_samples); j++) {
224 if (max_buf[j] > max_buf[peak_limiter->max_idx])
225 peak_limiter->max_idx = j;
226 }
227 } else if (tmp >= max_buf[peak_limiter->max_idx]) {
228 peak_limiter->max_idx = peak_limiter->cir_buf_pnt;
229 }
230 peak_limiter->cir_buf_pnt++;
231
232 if (peak_limiter->cir_buf_pnt == (WORD32)(attack_time_samples))
233 peak_limiter->cir_buf_pnt = 0;
234 maximum = max_buf[peak_limiter->max_idx];
235
236 if (maximum > limit_threshold) {
237 gain = limit_threshold / maximum;
238 } else {
239 gain = 1;
240 }
241
242 if (gain < pre_smoothed_gain) {
243 gain_modified =
244 MIN(gain_modified,
245 (gain - 0.1f * (FLOAT32)pre_smoothed_gain) * 1.11111111f);
246
247 } else {
248 gain_modified = gain;
249 }
250
251 if (gain_modified < pre_smoothed_gain) {
252 pre_smoothed_gain =
253 attack_constant * (pre_smoothed_gain - gain_modified) +
254 gain_modified;
255 pre_smoothed_gain = MAX(pre_smoothed_gain, gain);
256 } else {
257 pre_smoothed_gain =
258 release_constant * (pre_smoothed_gain - gain_modified) +
259 gain_modified;
260 }
261
262 gain = (FLOAT32)pre_smoothed_gain;
263
264 for (j = 0; j < num_channels; j++) {
265 WORD64 tmp_fix;
266 tmp = delayed_input[delayed_input_index * num_channels + j];
267 FLOAT32 gain_t = (FLOAT32)(1 << *(qshift_adj + j));
268 delayed_input[delayed_input_index * num_channels + j] =
269 samples[i * num_channels + j] * gain_t;
270
271 tmp *= gain;
272
273 tmp_fix = (WORD64)tmp;
274
275 if (tmp_fix > limit_threshold)
276 tmp_fix = limit_threshold;
277 else if (tmp_fix < -limit_threshold)
278 tmp_fix = -limit_threshold;
279
280 samples[i * num_channels + j] = (WORD32)tmp_fix;
281 }
282
283 delayed_input_index++;
284 if (delayed_input_index >= attack_time_samples) delayed_input_index = 0;
285
286 if (gain < min_gain) min_gain = gain;
287 }
288 } else {
289 for (i = 0; i < frame_len; i++) {
290 for (j = 0; j < num_channels; j++) {
291 tmp = delayed_input[delayed_input_index * num_channels + j];
292 FLOAT32 gain_t = (FLOAT32)(1 << *(qshift_adj + j));
293 delayed_input[delayed_input_index * num_channels + j] =
294 samples[i * num_channels + j] * gain_t;
295 samples[i * num_channels + j] = (WORD32)tmp;
296 }
297
298 delayed_input_index++;
299 if (delayed_input_index >= attack_time_samples) delayed_input_index = 0;
300 }
301 }
302
303 peak_limiter->gain_modified = gain_modified;
304 peak_limiter->delayed_input_index = delayed_input_index;
305 peak_limiter->pre_smoothed_gain = pre_smoothed_gain;
306 peak_limiter->min_gain = min_gain;
307
308 return;
309 }
310
311 /**
312 * ixheaacd_scale_adjust
313 *
314 * \brief Scale adjust process
315 *
316 * \param [in/out] samples
317 * \param [in] qshift_adj
318 * \param [in] frame_len
319 *
320 * \return WORD32
321 *
322 */
323
ixheaacd_scale_adjust(WORD32 * samples,UWORD32 frame_len,WORD8 * qshift_adj,WORD num_channels)324 VOID ixheaacd_scale_adjust(WORD32 *samples, UWORD32 frame_len,
325 WORD8 *qshift_adj, WORD num_channels) {
326 UWORD32 i;
327 WORD32 j;
328 for (i = 0; i < frame_len; i++) {
329 for (j = 0; j < num_channels; j++) {
330 WORD32 gain_t = (WORD32)(1 << *(qshift_adj + j));
331 samples[i * num_channels + j] = (samples[i * num_channels + j] * gain_t);
332 }
333 }
334 }