Home | History | Annotate | Download | only in drc_src
      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 <stdio.h>
     23 #include <string.h>
     24 
     25 #include "impd_type_def.h"
     26 #include "impd_drc_peak_limiter.h"
     27 
     28 #ifndef max
     29 #define max(a, b) (((a) > (b)) ? (a) : (b))
     30 #endif
     31 #ifndef min
     32 #define min(a, b) (((a) < (b)) ? (a) : (b))
     33 #endif
     34 
     35 WORD32 impd_peak_limiter_init(ia_drc_peak_limiter_struct *peak_limiter,
     36                               FLOAT32 attack_time, FLOAT32 release_time,
     37                               FLOAT32 limit_threshold, UWORD32 num_channels,
     38                               UWORD32 sample_rate, FLOAT32 *buffer) {
     39   UWORD32 attack;
     40   attack = (UWORD32)(attack_time * sample_rate / 1000);
     41 
     42   if (attack < 1) return 0;
     43 
     44   peak_limiter->max_buf = buffer;
     45   peak_limiter->delayed_input = buffer + attack * 4 + 32;
     46 
     47   peak_limiter->delayed_input_index = 0;
     48   peak_limiter->attack_time = attack_time;
     49   peak_limiter->release_time = release_time;
     50   peak_limiter->attack_time_samples = attack;
     51   peak_limiter->attack_constant = (FLOAT32)pow(0.1, 1.0 / (attack + 1));
     52   peak_limiter->release_constant =
     53       (FLOAT32)pow(0.1, 1.0 / (release_time * sample_rate / 1000 + 1));
     54   peak_limiter->limit_threshold = limit_threshold;
     55   peak_limiter->num_channels = num_channels;
     56   peak_limiter->sample_rate = sample_rate;
     57   peak_limiter->min_gain = 1.0f;
     58   peak_limiter->limiter_on = 1;
     59   peak_limiter->pre_smoothed_gain = 1.0f;
     60   peak_limiter->gain_modified = 1.0f;
     61 
     62   return 0;
     63 }
     64 
     65 WORD32 impd_peak_limiter_reinit(ia_drc_peak_limiter_struct *peak_limiter) {
     66   if (peak_limiter) {
     67     peak_limiter->delayed_input_index = 0;
     68     peak_limiter->pre_smoothed_gain = 1.0f;
     69     peak_limiter->gain_modified = 1.0f;
     70     peak_limiter->min_gain = 1.0f;
     71     memset(peak_limiter->max_buf, 0,
     72            (peak_limiter->attack_time_samples + 1) * sizeof(FLOAT32));
     73     memset(peak_limiter->delayed_input, 0, peak_limiter->attack_time_samples *
     74                                                peak_limiter->num_channels *
     75                                                sizeof(FLOAT32));
     76   }
     77 
     78   return 0;
     79 }
     80 
     81 WORD32 impd_limiter_process(ia_drc_peak_limiter_struct *peak_limiter,
     82                             FLOAT32 *samples, UWORD32 frame_len) {
     83   UWORD32 i, j;
     84   FLOAT32 tmp, gain;
     85   FLOAT32 min_gain = 1;
     86   FLOAT32 maximum, sectionMaximum;
     87   UWORD32 num_channels = peak_limiter->num_channels;
     88   UWORD32 attack_time_samples = peak_limiter->attack_time_samples;
     89   FLOAT32 attack_constant = peak_limiter->attack_constant;
     90   FLOAT32 release_constant = peak_limiter->release_constant;
     91   FLOAT32 limit_threshold = peak_limiter->limit_threshold;
     92   FLOAT32 *max_buf = peak_limiter->max_buf;
     93   FLOAT32 gain_modified = peak_limiter->gain_modified;
     94   FLOAT32 *delayed_input = peak_limiter->delayed_input;
     95   UWORD32 delayed_input_index = peak_limiter->delayed_input_index;
     96   FLOAT64 pre_smoothed_gain = peak_limiter->pre_smoothed_gain;
     97 
     98   if (peak_limiter->limiter_on || (FLOAT32)pre_smoothed_gain < 1.0f) {
     99     for (i = 0; i < frame_len; i++) {
    100       tmp = 0.0f;
    101       for (j = 0; j < num_channels; j++) {
    102         tmp = max(tmp, (FLOAT32)fabs(samples[i * num_channels + j]));
    103       }
    104 
    105       for (j = attack_time_samples; j > 0; j--) {
    106         max_buf[j] = max_buf[j - 1];
    107       }
    108       max_buf[0] = tmp;
    109       sectionMaximum = tmp;
    110       for (j = 1; j < (attack_time_samples + 1); j++) {
    111         if (max_buf[j] > sectionMaximum) sectionMaximum = max_buf[j];
    112       }
    113       maximum = sectionMaximum;
    114 
    115       if (maximum > limit_threshold) {
    116         gain = limit_threshold / maximum;
    117       } else {
    118         gain = 1;
    119       }
    120 
    121       if (gain < pre_smoothed_gain) {
    122         gain_modified =
    123             min(gain_modified,
    124                 (gain - 0.1f * (FLOAT32)pre_smoothed_gain) * 1.11111111f);
    125       } else {
    126         gain_modified = gain;
    127       }
    128 
    129       if (gain_modified < pre_smoothed_gain) {
    130         pre_smoothed_gain =
    131             attack_constant * (pre_smoothed_gain - gain_modified) +
    132             gain_modified;
    133         pre_smoothed_gain = max(pre_smoothed_gain, gain);
    134       } else {
    135         pre_smoothed_gain =
    136             release_constant * (pre_smoothed_gain - gain_modified) +
    137             gain_modified;
    138       }
    139 
    140       gain = (FLOAT32)pre_smoothed_gain;
    141 
    142       for (j = 0; j < num_channels; j++) {
    143         tmp = delayed_input[delayed_input_index * num_channels + j];
    144         delayed_input[delayed_input_index * num_channels + j] =
    145             samples[i * num_channels + j];
    146 
    147         tmp *= gain;
    148         if (tmp > limit_threshold)
    149           tmp = limit_threshold;
    150         else if (tmp < -limit_threshold)
    151           tmp = -limit_threshold;
    152 
    153         samples[i * num_channels + j] = tmp;
    154       }
    155 
    156       delayed_input_index++;
    157       if (delayed_input_index >= attack_time_samples) delayed_input_index = 0;
    158 
    159       if (gain < min_gain) min_gain = gain;
    160     }
    161   } else {
    162     for (i = 0; i < frame_len; i++) {
    163       for (j = 0; j < num_channels; j++) {
    164         tmp = delayed_input[delayed_input_index * num_channels + j];
    165         delayed_input[delayed_input_index * num_channels + j] =
    166             samples[i * num_channels + j];
    167         samples[i * num_channels + j] = tmp;
    168       }
    169 
    170       delayed_input_index++;
    171       if (delayed_input_index >= attack_time_samples) delayed_input_index = 0;
    172     }
    173   }
    174 
    175   peak_limiter->gain_modified = gain_modified;
    176   peak_limiter->delayed_input_index = delayed_input_index;
    177   peak_limiter->pre_smoothed_gain = pre_smoothed_gain;
    178   peak_limiter->min_gain = min_gain;
    179 
    180   return 0;
    181 }
    182