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