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 <math.h>
21#include "impd_type_def.h"
22#include "impd_memory_standards.h"
23#include "impd_drc_bitbuffer.h"
24#include "impd_drc_extr_delta_coded_info.h"
25#include "impd_drc_common.h"
26#include "impd_drc_struct.h"
27#include "impd_drc_interface.h"
28
29#include "impd_drc_bitstream_dec_api.h"
30#include "impd_drc_gain_dec.h"
31#include "impd_drc_filter_bank.h"
32#include "impd_drc_multi_band.h"
33#include "impd_drc_process_audio.h"
34#include "impd_parametric_drc_dec.h"
35#include "impd_drc_eq.h"
36#include "impd_drc_gain_decoder.h"
37#include "impd_drc_selection_process.h"
38
39#include "impd_drc_peak_limiter.h"
40#include "impd_drc_api_struct_def.h"
41
42#define BITSTREAM_FILE_FORMAT_SPLIT 1
43
44static WORD32 impd_down_mix(
45    ia_drc_sel_proc_output_struct *uni_drc_sel_proc_output,
46    FLOAT32 **input_audio, WORD32 frame_len) {
47  WORD32 num_base_ch = uni_drc_sel_proc_output->base_channel_count;
48  WORD32 num_target_ch = uni_drc_sel_proc_output->target_channel_count;
49  WORD32 i, i_ch, o_ch;
50  FLOAT32 tmp_out[MAX_CHANNEL_COUNT];
51
52  if (uni_drc_sel_proc_output->downmix_matrix_present == 0) return 0;
53
54  if (input_audio == 0) return 0;
55
56  if (num_target_ch > MAX_CHANNEL_COUNT) return -1;
57
58  if (num_target_ch > num_base_ch) return -1;
59
60  for (i = 0; i < frame_len; i++) {
61    for (o_ch = 0; o_ch < num_target_ch; o_ch++) {
62      tmp_out[o_ch] = 0.0f;
63      for (i_ch = 0; i_ch < num_base_ch; i_ch++) {
64        tmp_out[o_ch] += input_audio[i_ch][i] *
65                         uni_drc_sel_proc_output->downmix_matrix[i_ch][o_ch];
66      }
67    }
68    for (o_ch = 0; o_ch < num_target_ch; o_ch++) {
69      input_audio[o_ch][i] = tmp_out[o_ch];
70    }
71    for (; o_ch < num_base_ch; o_ch++) {
72      input_audio[o_ch][i] = 0.0f;
73    }
74  }
75
76  return 0;
77}
78
79WORD32 impd_init_process_audio_main_qmf(ia_drc_api_struct *p_obj_drc)
80
81{
82  WORD32 error = 0, i, j, num_samples_per_channel;
83  FLOAT32 *input_buffer;
84  FLOAT32 *output_buffer;
85  FLOAT32 *audio_io_buf_real[10];
86  FLOAT32 *audio_io_buf_imag[10];
87  FLOAT32 *scratch_buffer;
88  WORD32 last_frame = 0;
89  scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1];
90  input_buffer = (FLOAT32 *)p_obj_drc->pp_mem[2];
91  output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
92
93  if (p_obj_drc->p_state->ui_in_bytes <= 0) {
94    p_obj_drc->p_state->ui_out_bytes = 0;
95    return 0;
96  }
97
98  if ((p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in /
99       (p_obj_drc->str_config.pcm_size >> 3)) <
100      (UWORD32)p_obj_drc->str_config.frame_size)
101    last_frame = 1;
102  for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) {
103    audio_io_buf_real[i] =
104        scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32);
105    audio_io_buf_imag[i] =
106        scratch_buffer +
107        p_obj_drc->str_config.num_ch_in * p_obj_drc->str_config.frame_size +
108        p_obj_drc->str_config.num_ch_in * 64 +
109        i * (p_obj_drc->str_config.frame_size + 64);
110    for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
111      audio_io_buf_real[i][j] =
112          input_buffer[j * p_obj_drc->str_config.num_ch_in + i];
113      audio_io_buf_imag[i][j] =
114          input_buffer[p_obj_drc->str_config.num_ch_in *
115                           p_obj_drc->str_config.frame_size +
116                       j * p_obj_drc->str_config.num_ch_in + i];
117    }
118  }
119
120  error = impd_process_drc_bitstream_dec_gain(
121      p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf,
122      p_obj_drc->str_payload.pstr_drc_config,
123      p_obj_drc->str_payload.pstr_drc_gain,
124      &p_obj_drc->str_bit_handler
125           .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs],
126      p_obj_drc->str_bit_handler.num_bytes_bs,
127      p_obj_drc->str_bit_handler.num_bits_offset_bs,
128      &p_obj_drc->str_bit_handler.num_bits_read_bs);
129
130  if (error > PROC_COMPLETE) return -1;
131
132  p_obj_drc->str_bit_handler.num_bytes_read_bs =
133      (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3);
134  p_obj_drc->str_bit_handler.num_bits_offset_bs =
135      (p_obj_drc->str_bit_handler.num_bits_read_bs & 7);
136  p_obj_drc->str_bit_handler.byte_index_bs +=
137      p_obj_drc->str_bit_handler.num_bytes_read_bs;
138  if (p_obj_drc->str_bit_handler.gain_stream_flag ==
139      0)  // ITTIAM: Flag for applying gain frame by frame
140  {
141    p_obj_drc->str_bit_handler.num_bytes_bs -=
142        p_obj_drc->str_bit_handler.num_bytes_read_bs;
143  }
144
145  if (p_obj_drc->str_config.bitstream_file_format ==
146      BITSTREAM_FILE_FORMAT_SPLIT) {
147    if (p_obj_drc->str_bit_handler.num_bits_offset_bs != 0) {
148      p_obj_drc->str_bit_handler.num_bits_read_bs =
149          p_obj_drc->str_bit_handler.num_bits_read_bs + 8 -
150          p_obj_drc->str_bit_handler.num_bits_offset_bs;
151      p_obj_drc->str_bit_handler.num_bytes_read_bs =
152          p_obj_drc->str_bit_handler.num_bytes_read_bs + 1;
153      p_obj_drc->str_bit_handler.num_bits_offset_bs = 0;
154      p_obj_drc->str_bit_handler.byte_index_bs =
155          p_obj_drc->str_bit_handler.byte_index_bs + 1;
156      if (p_obj_drc->str_bit_handler.gain_stream_flag ==
157          0)  // ITTIAM: Flag for applying gain frame by frame
158      {
159        p_obj_drc->str_bit_handler.num_bytes_bs =
160            p_obj_drc->str_bit_handler.num_bytes_bs - 1;
161      }
162    }
163  }
164
165  error = impd_drc_process_freq_domain(
166      p_obj_drc->str_payload.pstr_gain_dec[0],
167      p_obj_drc->str_payload.pstr_drc_config,
168      p_obj_drc->str_payload.pstr_drc_gain, audio_io_buf_real,
169      audio_io_buf_imag, p_obj_drc->str_payload.pstr_drc_sel_proc_output
170                             ->loudness_normalization_gain_db,
171      p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost,
172      p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress,
173      p_obj_drc->str_payload.pstr_drc_sel_proc_output
174          ->drc_characteristic_target);
175  if (error) return -1;
176
177  error = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output,
178                        audio_io_buf_real, p_obj_drc->str_config.frame_size);
179  if (error) return -1;
180
181  error = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output,
182                        audio_io_buf_imag, p_obj_drc->str_config.frame_size);
183  if (error) return -1;
184
185  error = impd_drc_process_freq_domain(
186      p_obj_drc->str_payload.pstr_gain_dec[1],
187      p_obj_drc->str_payload.pstr_drc_config,
188      p_obj_drc->str_payload.pstr_drc_gain, audio_io_buf_real,
189      audio_io_buf_imag, p_obj_drc->str_payload.pstr_drc_sel_proc_output
190                             ->loudness_normalization_gain_db,
191      p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost,
192      p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress,
193      p_obj_drc->str_payload.pstr_drc_sel_proc_output
194          ->drc_characteristic_target);
195  if (error) return -1;
196
197  if (p_obj_drc->str_payload.pstr_drc_sel_proc_output
198          ->loudness_normalization_gain_db != 0.0f) {
199    FLOAT32 loudness_normalization_gain =
200        (FLOAT32)pow(10.0, p_obj_drc->str_payload.pstr_drc_sel_proc_output
201                                   ->loudness_normalization_gain_db /
202                               20.0);
203    for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
204      for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
205        audio_io_buf_real[i][j] *= loudness_normalization_gain;
206        audio_io_buf_imag[i][j] *= loudness_normalization_gain;
207      }
208    }
209  }
210  num_samples_per_channel = p_obj_drc->str_config.frame_size;
211
212  for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
213    for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
214      output_buffer[j * p_obj_drc->str_config.num_ch_out + i] =
215          audio_io_buf_real[i][j];
216      output_buffer[p_obj_drc->str_config.frame_size *
217                        p_obj_drc->str_config.num_ch_in +
218                    j * p_obj_drc->str_config.num_ch_out + i] =
219          audio_io_buf_imag[i][j];
220    }
221  }
222  p_obj_drc->p_state->ui_out_bytes =
223      p_obj_drc->str_config.num_ch_out * (p_obj_drc->str_config.frame_size) * 4;
224  p_obj_drc->p_state->ui_out_bytes =
225      p_obj_drc->str_config.num_ch_out *
226      (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in);
227
228  if (last_frame == 0) {
229    if (p_obj_drc->str_config.bitstream_file_format !=
230        BITSTREAM_FILE_FORMAT_SPLIT) {
231      error = impd_process_drc_bitstream_dec(
232          p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf,
233          p_obj_drc->str_payload.pstr_drc_config,
234          p_obj_drc->str_payload.pstr_loudness_info,
235          &p_obj_drc->str_bit_handler
236               .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs],
237          p_obj_drc->str_bit_handler.num_bytes_bs,
238          p_obj_drc->str_bit_handler.num_bits_offset_bs,
239          &p_obj_drc->str_bit_handler.num_bits_read_bs);
240
241      if (error > PROC_COMPLETE) return -1;
242
243      p_obj_drc->str_bit_handler.num_bytes_read_bs =
244          (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3);
245      p_obj_drc->str_bit_handler.num_bits_offset_bs =
246          (p_obj_drc->str_bit_handler.num_bits_read_bs & 7);
247      p_obj_drc->str_bit_handler.byte_index_bs +=
248          p_obj_drc->str_bit_handler.num_bytes_read_bs;
249      p_obj_drc->str_bit_handler.num_bytes_bs -=
250          p_obj_drc->str_bit_handler.num_bytes_read_bs;
251    }
252  }
253  return error;
254}
255