/src/aac/libDRCdec/src/FDK_drcDecLib.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /************************* MPEG-D DRC decoder library ************************** |
96 | | |
97 | | Author(s): Bernhard Neugebauer |
98 | | |
99 | | Description: MPEG-D DRC Decoder |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "drcDec_reader.h" |
104 | | #include "drcDec_gainDecoder.h" |
105 | | #include "FDK_drcDecLib.h" |
106 | | |
107 | | #include "drcDec_selectionProcess.h" |
108 | | #include "drcDec_tools.h" |
109 | | |
110 | | /* Decoder library info */ |
111 | | #define DRCDEC_LIB_VL0 2 |
112 | | #define DRCDEC_LIB_VL1 1 |
113 | | #define DRCDEC_LIB_VL2 0 |
114 | 0 | #define DRCDEC_LIB_TITLE "MPEG-D DRC Decoder Lib" |
115 | | #ifdef SUPPRESS_BUILD_DATE_INFO |
116 | | #define DRCDEC_LIB_BUILD_DATE "" |
117 | | #define DRCDEC_LIB_BUILD_TIME "" |
118 | | #else |
119 | 0 | #define DRCDEC_LIB_BUILD_DATE __DATE__ |
120 | 0 | #define DRCDEC_LIB_BUILD_TIME __TIME__ |
121 | | #endif |
122 | | |
123 | | typedef enum { |
124 | | DRC_DEC_NOT_INITIALIZED = 0, |
125 | | DRC_DEC_INITIALIZED, |
126 | | DRC_DEC_NEW_GAIN_PAYLOAD, |
127 | | DRC_DEC_INTERPOLATION_PREPARED |
128 | | } DRC_DEC_STATUS; |
129 | | |
130 | | struct s_drc_decoder { |
131 | | DRC_DEC_CODEC_MODE codecMode; |
132 | | DRC_DEC_FUNCTIONAL_RANGE functionalRange; |
133 | | DRC_DEC_STATUS status; |
134 | | |
135 | | /* handles of submodules */ |
136 | | HANDLE_DRC_GAIN_DECODER hGainDec; |
137 | | HANDLE_DRC_SELECTION_PROCESS hSelectionProc; |
138 | | int selProcInputDiff; |
139 | | |
140 | | /* data structs */ |
141 | | UNI_DRC_CONFIG uniDrcConfig; |
142 | | LOUDNESS_INFO_SET loudnessInfoSet; |
143 | | UNI_DRC_GAIN uniDrcGain; |
144 | | |
145 | | SEL_PROC_OUTPUT selProcOutput; |
146 | | } DRC_DECODER; |
147 | | |
148 | 0 | static int _getGainStatus(HANDLE_UNI_DRC_GAIN hUniDrcGain) { |
149 | 0 | return hUniDrcGain->status; |
150 | 0 | } |
151 | | |
152 | | static int isResetNeeded(HANDLE_DRC_DECODER hDrcDec, |
153 | 0 | const SEL_PROC_OUTPUT oldSelProcOutput) { |
154 | 0 | int i, resetNeeded = 0; |
155 | |
|
156 | 0 | if (hDrcDec->selProcOutput.numSelectedDrcSets != |
157 | 0 | oldSelProcOutput.numSelectedDrcSets) { |
158 | 0 | resetNeeded = 1; |
159 | 0 | } else { |
160 | 0 | for (i = 0; i < hDrcDec->selProcOutput.numSelectedDrcSets; i++) { |
161 | 0 | if (hDrcDec->selProcOutput.selectedDrcSetIds[i] != |
162 | 0 | oldSelProcOutput.selectedDrcSetIds[i]) |
163 | 0 | resetNeeded = 1; |
164 | 0 | if (hDrcDec->selProcOutput.selectedDownmixIds[i] != |
165 | 0 | oldSelProcOutput.selectedDownmixIds[i]) |
166 | 0 | resetNeeded = 1; |
167 | 0 | } |
168 | 0 | } |
169 | |
|
170 | 0 | if (hDrcDec->selProcOutput.boost != oldSelProcOutput.boost) resetNeeded = 1; |
171 | 0 | if (hDrcDec->selProcOutput.compress != oldSelProcOutput.compress) |
172 | 0 | resetNeeded = 1; |
173 | | |
174 | | /* Note: Changes in downmix matrix are not caught, as they don't affect the |
175 | | * DRC gain decoder */ |
176 | |
|
177 | 0 | return resetNeeded; |
178 | 0 | } |
179 | | |
180 | 0 | static void startSelectionProcess(HANDLE_DRC_DECODER hDrcDec) { |
181 | 0 | int uniDrcConfigHasChanged = 0; |
182 | 0 | SEL_PROC_OUTPUT oldSelProcOutput = hDrcDec->selProcOutput; |
183 | |
|
184 | 0 | if (!hDrcDec->status) return; |
185 | | |
186 | 0 | if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { |
187 | 0 | uniDrcConfigHasChanged = hDrcDec->uniDrcConfig.diff; |
188 | 0 | if (hDrcDec->uniDrcConfig.diff || hDrcDec->loudnessInfoSet.diff || |
189 | 0 | hDrcDec->selProcInputDiff) { |
190 | | /* in case of an error, signal that selection process was not successful |
191 | | */ |
192 | 0 | hDrcDec->selProcOutput.numSelectedDrcSets = 0; |
193 | |
|
194 | 0 | drcDec_SelectionProcess_Process( |
195 | 0 | hDrcDec->hSelectionProc, &(hDrcDec->uniDrcConfig), |
196 | 0 | &(hDrcDec->loudnessInfoSet), &(hDrcDec->selProcOutput)); |
197 | |
|
198 | 0 | hDrcDec->selProcInputDiff = 0; |
199 | 0 | hDrcDec->uniDrcConfig.diff = 0; |
200 | 0 | hDrcDec->loudnessInfoSet.diff = 0; |
201 | 0 | } |
202 | 0 | } |
203 | |
|
204 | 0 | if (hDrcDec->functionalRange & DRC_DEC_GAIN) { |
205 | 0 | if (isResetNeeded(hDrcDec, oldSelProcOutput) || uniDrcConfigHasChanged) { |
206 | 0 | drcDec_GainDecoder_Config(hDrcDec->hGainDec, &(hDrcDec->uniDrcConfig), |
207 | 0 | hDrcDec->selProcOutput.numSelectedDrcSets, |
208 | 0 | hDrcDec->selProcOutput.selectedDrcSetIds, |
209 | 0 | hDrcDec->selProcOutput.selectedDownmixIds); |
210 | 0 | } |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | DRC_DEC_ERROR |
215 | | FDK_drcDec_Open(HANDLE_DRC_DECODER* phDrcDec, |
216 | 0 | const DRC_DEC_FUNCTIONAL_RANGE functionalRange) { |
217 | 0 | DRC_ERROR dErr = DE_OK; |
218 | 0 | DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
219 | 0 | HANDLE_DRC_DECODER hDrcDec; |
220 | |
|
221 | 0 | *phDrcDec = (HANDLE_DRC_DECODER)FDKcalloc(1, sizeof(DRC_DECODER)); |
222 | 0 | if (!*phDrcDec) return DRC_DEC_OUT_OF_MEMORY; |
223 | 0 | hDrcDec = *phDrcDec; |
224 | |
|
225 | 0 | hDrcDec->functionalRange = functionalRange; |
226 | |
|
227 | 0 | hDrcDec->status = DRC_DEC_NOT_INITIALIZED; |
228 | 0 | hDrcDec->codecMode = DRC_DEC_CODEC_MODE_UNDEFINED; |
229 | |
|
230 | 0 | if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { |
231 | 0 | sErr = drcDec_SelectionProcess_Create(&(hDrcDec->hSelectionProc)); |
232 | 0 | if (sErr) return DRC_DEC_OUT_OF_MEMORY; |
233 | 0 | sErr = drcDec_SelectionProcess_Init(hDrcDec->hSelectionProc); |
234 | 0 | if (sErr) return DRC_DEC_NOT_OK; |
235 | 0 | hDrcDec->selProcInputDiff = 1; |
236 | 0 | } |
237 | | |
238 | 0 | if (hDrcDec->functionalRange & DRC_DEC_GAIN) { |
239 | 0 | dErr = drcDec_GainDecoder_Open(&(hDrcDec->hGainDec)); |
240 | 0 | if (dErr) return DRC_DEC_OUT_OF_MEMORY; |
241 | 0 | } |
242 | | |
243 | 0 | return DRC_DEC_OK; |
244 | 0 | } |
245 | | |
246 | | DRC_DEC_ERROR |
247 | | FDK_drcDec_SetCodecMode(HANDLE_DRC_DECODER hDrcDec, |
248 | 0 | const DRC_DEC_CODEC_MODE codecMode) { |
249 | 0 | DRC_ERROR dErr = DE_OK; |
250 | 0 | DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
251 | |
|
252 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
253 | | |
254 | 0 | if (hDrcDec->codecMode == |
255 | 0 | DRC_DEC_CODEC_MODE_UNDEFINED) { /* Set codec mode, if it is set for the |
256 | | first time */ |
257 | 0 | hDrcDec->codecMode = codecMode; |
258 | |
|
259 | 0 | if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { |
260 | 0 | sErr = drcDec_SelectionProcess_SetCodecMode( |
261 | 0 | hDrcDec->hSelectionProc, (SEL_PROC_CODEC_MODE)codecMode); |
262 | 0 | if (sErr) return DRC_DEC_NOT_OK; |
263 | 0 | hDrcDec->selProcInputDiff = 1; |
264 | 0 | } |
265 | | |
266 | 0 | if (hDrcDec->functionalRange & DRC_DEC_GAIN) { |
267 | 0 | DELAY_MODE delayMode; |
268 | 0 | int timeDomainSupported; |
269 | 0 | SUBBAND_DOMAIN_MODE subbandDomainSupported; |
270 | |
|
271 | 0 | switch (hDrcDec->codecMode) { |
272 | 0 | case DRC_DEC_MPEG_4_AAC: |
273 | 0 | case DRC_DEC_MPEG_D_USAC: |
274 | 0 | case DRC_DEC_MPEG_H_3DA: |
275 | 0 | default: |
276 | 0 | delayMode = DM_REGULAR_DELAY; |
277 | 0 | } |
278 | |
|
279 | 0 | switch (hDrcDec->codecMode) { |
280 | 0 | case DRC_DEC_MPEG_4_AAC: |
281 | 0 | case DRC_DEC_MPEG_D_USAC: |
282 | 0 | timeDomainSupported = 1; |
283 | 0 | subbandDomainSupported = SDM_OFF; |
284 | 0 | break; |
285 | 0 | case DRC_DEC_MPEG_H_3DA: |
286 | 0 | timeDomainSupported = 1; |
287 | 0 | subbandDomainSupported = SDM_STFT256; |
288 | 0 | break; |
289 | | |
290 | 0 | case DRC_DEC_TEST_TIME_DOMAIN: |
291 | 0 | timeDomainSupported = 1; |
292 | 0 | subbandDomainSupported = SDM_OFF; |
293 | 0 | break; |
294 | 0 | case DRC_DEC_TEST_QMF_DOMAIN: |
295 | 0 | timeDomainSupported = 0; |
296 | 0 | subbandDomainSupported = SDM_QMF64; |
297 | 0 | break; |
298 | 0 | case DRC_DEC_TEST_STFT_DOMAIN: |
299 | 0 | timeDomainSupported = 0; |
300 | 0 | subbandDomainSupported = SDM_STFT256; |
301 | 0 | break; |
302 | | |
303 | 0 | default: |
304 | 0 | timeDomainSupported = 0; |
305 | 0 | subbandDomainSupported = SDM_OFF; |
306 | 0 | } |
307 | | |
308 | 0 | dErr = drcDec_GainDecoder_SetCodecDependentParameters( |
309 | 0 | hDrcDec->hGainDec, delayMode, timeDomainSupported, |
310 | 0 | subbandDomainSupported); |
311 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
312 | 0 | } |
313 | 0 | } |
314 | | |
315 | | /* Don't allow changing codecMode if it has already been set. */ |
316 | 0 | if (hDrcDec->codecMode != codecMode) return DRC_DEC_NOT_OK; |
317 | | |
318 | 0 | return DRC_DEC_OK; |
319 | 0 | } |
320 | | |
321 | | DRC_DEC_ERROR |
322 | | FDK_drcDec_Init(HANDLE_DRC_DECODER hDrcDec, const int frameSize, |
323 | 0 | const int sampleRate, const int baseChannelCount) { |
324 | 0 | DRC_ERROR dErr = DE_OK; |
325 | 0 | DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
326 | |
|
327 | 0 | if (hDrcDec == NULL || frameSize == 0 || sampleRate == 0 || |
328 | 0 | baseChannelCount == 0) |
329 | 0 | return DRC_DEC_OK; /* return without doing anything */ |
330 | | |
331 | 0 | if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { |
332 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
333 | 0 | hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, |
334 | 0 | (FIXP_DBL)baseChannelCount, &(hDrcDec->selProcInputDiff)); |
335 | 0 | if (sErr) return DRC_DEC_NOT_OK; |
336 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
337 | 0 | hDrcDec->hSelectionProc, SEL_PROC_SAMPLE_RATE, (FIXP_DBL)sampleRate, |
338 | 0 | &(hDrcDec->selProcInputDiff)); |
339 | 0 | if (sErr) return DRC_DEC_NOT_OK; |
340 | 0 | } |
341 | | |
342 | 0 | if (hDrcDec->functionalRange & DRC_DEC_GAIN) { |
343 | 0 | dErr = drcDec_GainDecoder_SetParam(hDrcDec->hGainDec, GAIN_DEC_FRAME_SIZE, |
344 | 0 | frameSize); |
345 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
346 | 0 | dErr = drcDec_GainDecoder_SetParam(hDrcDec->hGainDec, GAIN_DEC_SAMPLE_RATE, |
347 | 0 | sampleRate); |
348 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
349 | 0 | dErr = drcDec_GainDecoder_Init(hDrcDec->hGainDec); |
350 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
351 | 0 | } |
352 | | |
353 | 0 | hDrcDec->status = DRC_DEC_INITIALIZED; |
354 | |
|
355 | 0 | startSelectionProcess(hDrcDec); |
356 | |
|
357 | 0 | return DRC_DEC_OK; |
358 | 0 | } |
359 | | |
360 | | DRC_DEC_ERROR |
361 | 0 | FDK_drcDec_Close(HANDLE_DRC_DECODER* phDrcDec) { |
362 | 0 | HANDLE_DRC_DECODER hDrcDec; |
363 | |
|
364 | 0 | if (phDrcDec == NULL) { |
365 | 0 | return DRC_DEC_OK; |
366 | 0 | } |
367 | | |
368 | 0 | hDrcDec = *phDrcDec; |
369 | |
|
370 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
371 | | |
372 | 0 | if (hDrcDec->functionalRange & DRC_DEC_GAIN) { |
373 | 0 | drcDec_GainDecoder_Close(&(hDrcDec->hGainDec)); |
374 | 0 | } |
375 | |
|
376 | 0 | if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { |
377 | 0 | drcDec_SelectionProcess_Delete(&(hDrcDec->hSelectionProc)); |
378 | 0 | } |
379 | |
|
380 | 0 | FDKfree(*phDrcDec); |
381 | 0 | *phDrcDec = NULL; |
382 | |
|
383 | 0 | return DRC_DEC_OK; |
384 | 0 | } |
385 | | |
386 | | DRC_DEC_ERROR |
387 | | FDK_drcDec_SetParam(HANDLE_DRC_DECODER hDrcDec, |
388 | | const DRC_DEC_USERPARAM requestType, |
389 | 0 | const FIXP_DBL requestValue) { |
390 | 0 | DRC_ERROR dErr = DE_OK; |
391 | 0 | DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
392 | 0 | int invalidParameter = 0; |
393 | |
|
394 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
395 | | |
396 | 0 | if (hDrcDec->functionalRange & DRC_DEC_GAIN) { |
397 | 0 | switch (requestType) { |
398 | 0 | case DRC_DEC_SAMPLE_RATE: |
399 | 0 | dErr = drcDec_GainDecoder_SetParam( |
400 | 0 | hDrcDec->hGainDec, GAIN_DEC_SAMPLE_RATE, (int)requestValue); |
401 | 0 | if (dErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
402 | 0 | break; |
403 | 0 | case DRC_DEC_FRAME_SIZE: |
404 | 0 | dErr = drcDec_GainDecoder_SetParam( |
405 | 0 | hDrcDec->hGainDec, GAIN_DEC_FRAME_SIZE, (int)requestValue); |
406 | 0 | if (dErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
407 | 0 | break; |
408 | 0 | default: |
409 | 0 | invalidParameter |= DRC_DEC_GAIN; |
410 | 0 | } |
411 | 0 | } |
412 | | |
413 | 0 | if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { |
414 | 0 | switch (requestType) { |
415 | 0 | case DRC_DEC_BOOST: |
416 | 0 | sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, |
417 | 0 | SEL_PROC_BOOST, requestValue, |
418 | 0 | &(hDrcDec->selProcInputDiff)); |
419 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
420 | 0 | break; |
421 | 0 | case DRC_DEC_COMPRESS: |
422 | 0 | sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, |
423 | 0 | SEL_PROC_COMPRESS, requestValue, |
424 | 0 | &(hDrcDec->selProcInputDiff)); |
425 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
426 | 0 | break; |
427 | 0 | case DRC_DEC_LOUDNESS_NORMALIZATION_ON: |
428 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
429 | 0 | hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON, |
430 | 0 | requestValue, &(hDrcDec->selProcInputDiff)); |
431 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
432 | 0 | break; |
433 | 0 | case DRC_DEC_TARGET_LOUDNESS: |
434 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
435 | 0 | hDrcDec->hSelectionProc, SEL_PROC_TARGET_LOUDNESS, requestValue, |
436 | 0 | &(hDrcDec->selProcInputDiff)); |
437 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
438 | 0 | break; |
439 | 0 | case DRC_DEC_EFFECT_TYPE: |
440 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
441 | 0 | hDrcDec->hSelectionProc, SEL_PROC_EFFECT_TYPE, requestValue, |
442 | 0 | &(hDrcDec->selProcInputDiff)); |
443 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
444 | 0 | break; |
445 | 0 | case DRC_DEC_DOWNMIX_ID: |
446 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
447 | 0 | hDrcDec->hSelectionProc, SEL_PROC_DOWNMIX_ID, requestValue, |
448 | 0 | &(hDrcDec->selProcInputDiff)); |
449 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
450 | 0 | break; |
451 | 0 | case DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED: |
452 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
453 | 0 | hDrcDec->hSelectionProc, SEL_PROC_TARGET_CHANNEL_COUNT, |
454 | 0 | requestValue, &(hDrcDec->selProcInputDiff)); |
455 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
456 | 0 | break; |
457 | 0 | case DRC_DEC_BASE_CHANNEL_COUNT: |
458 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
459 | 0 | hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, requestValue, |
460 | 0 | &(hDrcDec->selProcInputDiff)); |
461 | 0 | if (sErr) return DRC_DEC_NOT_OK; |
462 | 0 | break; |
463 | 0 | case DRC_DEC_LOUDNESS_MEASUREMENT_METHOD: |
464 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
465 | 0 | hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_MEASUREMENT_METHOD, |
466 | 0 | requestValue, &(hDrcDec->selProcInputDiff)); |
467 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
468 | 0 | break; |
469 | 0 | case DRC_DEC_ALBUM_MODE: |
470 | 0 | sErr = drcDec_SelectionProcess_SetParam( |
471 | 0 | hDrcDec->hSelectionProc, SEL_PROC_ALBUM_MODE, requestValue, |
472 | 0 | &(hDrcDec->selProcInputDiff)); |
473 | 0 | if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; |
474 | 0 | break; |
475 | 0 | default: |
476 | 0 | invalidParameter |= DRC_DEC_SELECTION; |
477 | 0 | } |
478 | 0 | } |
479 | | |
480 | 0 | if (invalidParameter == hDrcDec->functionalRange) |
481 | 0 | return DRC_DEC_INVALID_PARAM; |
482 | | |
483 | | /* All parameters need a new start of the selection process */ |
484 | 0 | startSelectionProcess(hDrcDec); |
485 | |
|
486 | 0 | return DRC_DEC_OK; |
487 | 0 | } |
488 | | |
489 | | LONG FDK_drcDec_GetParam(HANDLE_DRC_DECODER hDrcDec, |
490 | 0 | const DRC_DEC_USERPARAM requestType) { |
491 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
492 | | |
493 | 0 | switch (requestType) { |
494 | 0 | case DRC_DEC_BOOST: |
495 | 0 | return (LONG)hDrcDec->selProcOutput.boost; |
496 | 0 | case DRC_DEC_COMPRESS: |
497 | 0 | return (LONG)hDrcDec->selProcOutput.compress; |
498 | 0 | case DRC_DEC_IS_MULTIBAND_DRC_1: |
499 | 0 | return (LONG)bitstreamContainsMultibandDrc(&hDrcDec->uniDrcConfig, 0); |
500 | 0 | case DRC_DEC_IS_MULTIBAND_DRC_2: |
501 | 0 | return (LONG)bitstreamContainsMultibandDrc(&hDrcDec->uniDrcConfig, 0x7F); |
502 | 0 | case DRC_DEC_IS_ACTIVE: { |
503 | | /* MPEG-D DRC is considered active (and overrides MPEG-4 DRC), if |
504 | | * uniDrc payload is present (loudnessInfoSet and/or uniDrcConfig) |
505 | | * at least one of DRC and Loudness Control is switched on */ |
506 | 0 | int drcOn = drcDec_SelectionProcess_GetParam( |
507 | 0 | hDrcDec->hSelectionProc, SEL_PROC_DYNAMIC_RANGE_CONTROL_ON); |
508 | 0 | int lnOn = drcDec_SelectionProcess_GetParam( |
509 | 0 | hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON); |
510 | 0 | int uniDrcPayloadPresent = |
511 | 0 | (hDrcDec->loudnessInfoSet.loudnessInfoCount > 0); |
512 | 0 | uniDrcPayloadPresent |= |
513 | 0 | (hDrcDec->loudnessInfoSet.loudnessInfoAlbumCount > 0); |
514 | 0 | uniDrcPayloadPresent |= |
515 | 0 | (hDrcDec->uniDrcConfig.drcInstructionsUniDrcCount > 0); |
516 | 0 | uniDrcPayloadPresent |= |
517 | 0 | (hDrcDec->uniDrcConfig.downmixInstructionsCount > 0); |
518 | 0 | return (LONG)(uniDrcPayloadPresent && (drcOn || lnOn)); |
519 | 0 | } |
520 | 0 | case DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED: |
521 | 0 | return (LONG)hDrcDec->selProcOutput.targetChannelCount; |
522 | 0 | case DRC_DEC_OUTPUT_LOUDNESS: |
523 | 0 | return (LONG)hDrcDec->selProcOutput.outputLoudness; |
524 | 0 | default: |
525 | 0 | return 0; |
526 | 0 | } |
527 | 0 | } |
528 | | |
529 | | DRC_DEC_ERROR |
530 | | FDK_drcDec_SetInterfaceParameters(HANDLE_DRC_DECODER hDrcDec, |
531 | 0 | HANDLE_UNI_DRC_INTERFACE hUniDrcInterface) { |
532 | 0 | return DRC_DEC_UNSUPPORTED_FUNCTION; |
533 | 0 | } |
534 | | |
535 | | DRC_DEC_ERROR |
536 | | FDK_drcDec_SetSelectionProcessMpeghParameters_simple( |
537 | | HANDLE_DRC_DECODER hDrcDec, const int groupPresetIdRequested, |
538 | 0 | const int numGroupIdsRequested, const int* groupIdsRequested) { |
539 | 0 | return DRC_DEC_UNSUPPORTED_FUNCTION; |
540 | 0 | } |
541 | | |
542 | | DRC_DEC_ERROR |
543 | | FDK_drcDec_SetDownmixInstructions(HANDLE_DRC_DECODER hDrcDec, |
544 | | const int numDownmixId, const int* downmixId, |
545 | | const int* targetLayout, |
546 | 0 | const int* targetChannelCount) { |
547 | 0 | return DRC_DEC_UNSUPPORTED_FUNCTION; |
548 | 0 | } |
549 | | |
550 | | void FDK_drcDec_SetSelectionProcessOutput( |
551 | 0 | HANDLE_DRC_DECODER hDrcDec, HANDLE_SEL_PROC_OUTPUT hSelProcOutput) {} |
552 | | |
553 | | HANDLE_SEL_PROC_OUTPUT |
554 | 0 | FDK_drcDec_GetSelectionProcessOutput(HANDLE_DRC_DECODER hDrcDec) { |
555 | 0 | if (hDrcDec == NULL) return NULL; |
556 | | |
557 | 0 | return &(hDrcDec->selProcOutput); |
558 | 0 | } |
559 | | |
560 | | LONG /* FIXP_DBL, e = 7 */ |
561 | | FDK_drcDec_GetGroupLoudness(HANDLE_SEL_PROC_OUTPUT hSelProcOutput, |
562 | 0 | const int groupID, int* groupLoudnessAvailable) { |
563 | 0 | return (LONG)0; |
564 | 0 | } |
565 | | |
566 | | void FDK_drcDec_SetChannelGains(HANDLE_DRC_DECODER hDrcDec, |
567 | | const int numChannels, const int frameSize, |
568 | | FIXP_DBL* channelGainDb, FIXP_DBL* audioBuffer, |
569 | 0 | const int audioBufferChannelOffset) { |
570 | 0 | int err; |
571 | |
|
572 | 0 | if (hDrcDec == NULL) return; |
573 | | |
574 | 0 | err = drcDec_GainDecoder_SetLoudnessNormalizationGainDb( |
575 | 0 | hDrcDec->hGainDec, hDrcDec->selProcOutput.loudnessNormalizationGainDb); |
576 | 0 | if (err) return; |
577 | | |
578 | 0 | drcDec_GainDecoder_SetChannelGains(hDrcDec->hGainDec, numChannels, frameSize, |
579 | 0 | channelGainDb, audioBufferChannelOffset, |
580 | 0 | audioBuffer); |
581 | 0 | } |
582 | | |
583 | | DRC_DEC_ERROR |
584 | | FDK_drcDec_ReadUniDrcConfig(HANDLE_DRC_DECODER hDrcDec, |
585 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
586 | 0 | DRC_ERROR dErr = DE_OK; |
587 | |
|
588 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
589 | | |
590 | 0 | if (hDrcDec->codecMode == DRC_DEC_MPEG_D_USAC) { |
591 | 0 | dErr = drcDec_readUniDrcConfig(hBitstream, &(hDrcDec->uniDrcConfig)); |
592 | 0 | } else |
593 | 0 | return DRC_DEC_NOT_OK; |
594 | | |
595 | 0 | if (dErr) { |
596 | | /* clear config, if parsing error occured */ |
597 | 0 | FDKmemclear(&hDrcDec->uniDrcConfig, sizeof(hDrcDec->uniDrcConfig)); |
598 | 0 | hDrcDec->uniDrcConfig.diff = 1; |
599 | 0 | } |
600 | |
|
601 | 0 | startSelectionProcess(hDrcDec); |
602 | |
|
603 | 0 | return DRC_DEC_OK; |
604 | 0 | } |
605 | | |
606 | | DRC_DEC_ERROR |
607 | | FDK_drcDec_ReadDownmixInstructions_Box(HANDLE_DRC_DECODER hDrcDec, |
608 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
609 | 0 | DRC_ERROR dErr = DE_OK; |
610 | |
|
611 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
612 | | |
613 | 0 | return DRC_DEC_NOT_OK; |
614 | | |
615 | 0 | if (dErr) { |
616 | | /* clear config, if parsing error occurred */ |
617 | 0 | FDKmemclear(&hDrcDec->uniDrcConfig.downmixInstructions, |
618 | 0 | sizeof(hDrcDec->uniDrcConfig.downmixInstructions)); |
619 | 0 | hDrcDec->uniDrcConfig.downmixInstructionsCount = 0; |
620 | 0 | hDrcDec->uniDrcConfig.downmixInstructionsCountV0 = 0; |
621 | 0 | hDrcDec->uniDrcConfig.downmixInstructionsCountV1 = 0; |
622 | 0 | hDrcDec->uniDrcConfig.diff = 1; |
623 | 0 | } |
624 | |
|
625 | 0 | startSelectionProcess(hDrcDec); |
626 | |
|
627 | 0 | return DRC_DEC_OK; |
628 | 0 | } |
629 | | |
630 | | DRC_DEC_ERROR |
631 | | FDK_drcDec_ReadUniDrcInstructions_Box(HANDLE_DRC_DECODER hDrcDec, |
632 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
633 | 0 | DRC_ERROR dErr = DE_OK; |
634 | |
|
635 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
636 | | |
637 | 0 | return DRC_DEC_NOT_OK; |
638 | | |
639 | 0 | if (dErr) { |
640 | | /* clear config, if parsing error occurred */ |
641 | 0 | FDKmemclear(&hDrcDec->uniDrcConfig.drcInstructionsUniDrc, |
642 | 0 | sizeof(hDrcDec->uniDrcConfig.drcInstructionsUniDrc)); |
643 | 0 | hDrcDec->uniDrcConfig.drcInstructionsUniDrcCount = 0; |
644 | 0 | hDrcDec->uniDrcConfig.drcInstructionsUniDrcCountV0 = 0; |
645 | 0 | hDrcDec->uniDrcConfig.drcInstructionsUniDrcCountV1 = 0; |
646 | 0 | hDrcDec->uniDrcConfig.diff = 1; |
647 | 0 | } |
648 | |
|
649 | 0 | startSelectionProcess(hDrcDec); |
650 | |
|
651 | 0 | return DRC_DEC_OK; |
652 | 0 | } |
653 | | |
654 | | DRC_DEC_ERROR |
655 | | FDK_drcDec_ReadUniDrcCoefficients_Box(HANDLE_DRC_DECODER hDrcDec, |
656 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
657 | 0 | DRC_ERROR dErr = DE_OK; |
658 | |
|
659 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
660 | | |
661 | 0 | return DRC_DEC_NOT_OK; |
662 | | |
663 | 0 | if (dErr) { |
664 | | /* clear config, if parsing error occurred */ |
665 | 0 | FDKmemclear(&hDrcDec->uniDrcConfig.drcCoefficientsUniDrc, |
666 | 0 | sizeof(hDrcDec->uniDrcConfig.drcCoefficientsUniDrc)); |
667 | 0 | hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCount = 0; |
668 | 0 | hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCountV0 = 0; |
669 | 0 | hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCountV1 = 0; |
670 | 0 | hDrcDec->uniDrcConfig.diff = 1; |
671 | 0 | } |
672 | |
|
673 | 0 | startSelectionProcess(hDrcDec); |
674 | |
|
675 | 0 | return DRC_DEC_OK; |
676 | 0 | } |
677 | | |
678 | | DRC_DEC_ERROR |
679 | | FDK_drcDec_ReadLoudnessInfoSet(HANDLE_DRC_DECODER hDrcDec, |
680 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
681 | 0 | DRC_ERROR dErr = DE_OK; |
682 | |
|
683 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
684 | | |
685 | 0 | if (hDrcDec->codecMode == DRC_DEC_MPEG_D_USAC) { |
686 | 0 | dErr = drcDec_readLoudnessInfoSet(hBitstream, &(hDrcDec->loudnessInfoSet)); |
687 | 0 | } else |
688 | 0 | return DRC_DEC_NOT_OK; |
689 | | |
690 | 0 | if (dErr) { |
691 | | /* clear config, if parsing error occurred */ |
692 | 0 | FDKmemclear(&hDrcDec->loudnessInfoSet, sizeof(hDrcDec->loudnessInfoSet)); |
693 | 0 | hDrcDec->loudnessInfoSet.diff = 1; |
694 | 0 | } |
695 | |
|
696 | 0 | startSelectionProcess(hDrcDec); |
697 | |
|
698 | 0 | return DRC_DEC_OK; |
699 | 0 | } |
700 | | |
701 | | DRC_DEC_ERROR |
702 | | FDK_drcDec_ReadLoudnessBox(HANDLE_DRC_DECODER hDrcDec, |
703 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
704 | 0 | DRC_ERROR dErr = DE_OK; |
705 | |
|
706 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
707 | | |
708 | 0 | return DRC_DEC_NOT_OK; |
709 | | |
710 | 0 | if (dErr) { |
711 | | /* clear config, if parsing error occurred */ |
712 | 0 | FDKmemclear(&hDrcDec->loudnessInfoSet, sizeof(hDrcDec->loudnessInfoSet)); |
713 | 0 | hDrcDec->loudnessInfoSet.diff = 1; |
714 | 0 | } |
715 | |
|
716 | 0 | startSelectionProcess(hDrcDec); |
717 | |
|
718 | 0 | return DRC_DEC_OK; |
719 | 0 | } |
720 | | |
721 | | DRC_DEC_ERROR |
722 | | FDK_drcDec_ReadUniDrcGain(HANDLE_DRC_DECODER hDrcDec, |
723 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
724 | 0 | DRC_ERROR dErr = DE_OK; |
725 | |
|
726 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
727 | 0 | if (!hDrcDec->status) { |
728 | 0 | return DRC_DEC_OK; |
729 | 0 | } |
730 | | |
731 | 0 | dErr = drcDec_readUniDrcGain( |
732 | 0 | hBitstream, &(hDrcDec->uniDrcConfig), |
733 | 0 | drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec), |
734 | 0 | drcDec_GainDecoder_GetDeltaTminDefault(hDrcDec->hGainDec), |
735 | 0 | &(hDrcDec->uniDrcGain)); |
736 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
737 | | |
738 | 0 | if (_getGainStatus(&(hDrcDec->uniDrcGain))) { |
739 | 0 | hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD; |
740 | 0 | } |
741 | |
|
742 | 0 | return DRC_DEC_OK; |
743 | 0 | } |
744 | | |
745 | | DRC_DEC_ERROR |
746 | | FDK_drcDec_ReadUniDrc(HANDLE_DRC_DECODER hDrcDec, |
747 | 0 | HANDLE_FDK_BITSTREAM hBitstream) { |
748 | 0 | DRC_ERROR dErr = DE_OK; |
749 | |
|
750 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
751 | 0 | if (!hDrcDec->status) return DRC_DEC_NOT_READY; |
752 | | |
753 | 0 | dErr = drcDec_readUniDrc( |
754 | 0 | hBitstream, &(hDrcDec->uniDrcConfig), &(hDrcDec->loudnessInfoSet), |
755 | 0 | drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec), |
756 | 0 | drcDec_GainDecoder_GetDeltaTminDefault(hDrcDec->hGainDec), |
757 | 0 | &(hDrcDec->uniDrcGain)); |
758 | |
|
759 | 0 | startSelectionProcess(hDrcDec); |
760 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
761 | | |
762 | 0 | if (_getGainStatus(&(hDrcDec->uniDrcGain))) { |
763 | 0 | hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD; |
764 | 0 | } |
765 | |
|
766 | 0 | return DRC_DEC_OK; |
767 | 0 | } |
768 | | |
769 | | DRC_DEC_ERROR |
770 | 0 | FDK_drcDec_Preprocess(HANDLE_DRC_DECODER hDrcDec) { |
771 | 0 | DRC_ERROR dErr = DE_OK; |
772 | |
|
773 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
774 | 0 | if (!hDrcDec->status) return DRC_DEC_NOT_READY; |
775 | 0 | if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; |
776 | | |
777 | 0 | if (hDrcDec->status != DRC_DEC_NEW_GAIN_PAYLOAD) { |
778 | | /* no new gain payload was read, e.g. during concalment or flushing. |
779 | | Generate DRC gains based on the stored DRC gains of last frames */ |
780 | 0 | drcDec_GainDecoder_Conceal(hDrcDec->hGainDec, &(hDrcDec->uniDrcConfig), |
781 | 0 | &(hDrcDec->uniDrcGain)); |
782 | 0 | } |
783 | |
|
784 | 0 | dErr = drcDec_GainDecoder_Preprocess( |
785 | 0 | hDrcDec->hGainDec, &(hDrcDec->uniDrcGain), |
786 | 0 | hDrcDec->selProcOutput.loudnessNormalizationGainDb, |
787 | 0 | hDrcDec->selProcOutput.boost, hDrcDec->selProcOutput.compress); |
788 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
789 | 0 | hDrcDec->status = DRC_DEC_INTERPOLATION_PREPARED; |
790 | |
|
791 | 0 | return DRC_DEC_OK; |
792 | 0 | } |
793 | | |
794 | | DRC_DEC_ERROR |
795 | | FDK_drcDec_ProcessTime(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, |
796 | | const DRC_DEC_LOCATION drcLocation, |
797 | | const int channelOffset, const int drcChannelOffset, |
798 | | const int numChannelsProcessed, FIXP_DBL* realBuffer, |
799 | 0 | const int timeDataChannelOffset) { |
800 | 0 | DRC_ERROR dErr = DE_OK; |
801 | |
|
802 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
803 | 0 | if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; |
804 | 0 | if (hDrcDec->status != DRC_DEC_INTERPOLATION_PREPARED) |
805 | 0 | return DRC_DEC_NOT_READY; |
806 | | |
807 | 0 | dErr = drcDec_GainDecoder_ProcessTimeDomain( |
808 | 0 | hDrcDec->hGainDec, delaySamples, (GAIN_DEC_LOCATION)drcLocation, |
809 | 0 | channelOffset, drcChannelOffset, numChannelsProcessed, |
810 | 0 | timeDataChannelOffset, realBuffer); |
811 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
812 | | |
813 | 0 | return DRC_DEC_OK; |
814 | 0 | } |
815 | | |
816 | | DRC_DEC_ERROR |
817 | | FDK_drcDec_ProcessFreq(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, |
818 | | const DRC_DEC_LOCATION drcLocation, |
819 | | const int channelOffset, const int drcChannelOffset, |
820 | | const int numChannelsProcessed, |
821 | | const int processSingleTimeslot, FIXP_DBL** realBuffer, |
822 | 0 | FIXP_DBL** imagBuffer) { |
823 | 0 | DRC_ERROR dErr = DE_OK; |
824 | |
|
825 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
826 | 0 | if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; |
827 | 0 | if (hDrcDec->status != DRC_DEC_INTERPOLATION_PREPARED) |
828 | 0 | return DRC_DEC_NOT_READY; |
829 | | |
830 | 0 | dErr = drcDec_GainDecoder_ProcessSubbandDomain( |
831 | 0 | hDrcDec->hGainDec, delaySamples, (GAIN_DEC_LOCATION)drcLocation, |
832 | 0 | channelOffset, drcChannelOffset, numChannelsProcessed, |
833 | 0 | processSingleTimeslot, realBuffer, imagBuffer); |
834 | 0 | if (dErr) return DRC_DEC_NOT_OK; |
835 | | |
836 | 0 | return DRC_DEC_OK; |
837 | 0 | } |
838 | | |
839 | | DRC_DEC_ERROR |
840 | | FDK_drcDec_ApplyDownmix(HANDLE_DRC_DECODER hDrcDec, int* reverseInChannelMap, |
841 | | int* reverseOutChannelMap, FIXP_DBL* realBuffer, |
842 | 0 | int* pNChannels) { |
843 | 0 | SEL_PROC_OUTPUT* pSelProcOutput = &(hDrcDec->selProcOutput); |
844 | 0 | int baseChCnt = pSelProcOutput->baseChannelCount; |
845 | 0 | int targetChCnt = pSelProcOutput->targetChannelCount; |
846 | 0 | int frameSize, n, ic, oc; |
847 | 0 | FIXP_DBL tmp_out[8]; |
848 | 0 | FIXP_DBL* audioChannels[8]; |
849 | |
|
850 | 0 | if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; |
851 | 0 | if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; |
852 | | |
853 | | /* only downmix is performed here, no upmix. |
854 | | Downmix is only performed if downmix coefficients are provided. |
855 | | All other cases of downmix and upmix are treated by pcmDmx library. */ |
856 | 0 | if (pSelProcOutput->downmixMatrixPresent == 0) |
857 | 0 | return DRC_DEC_OK; /* no downmix */ |
858 | 0 | if (targetChCnt >= baseChCnt) return DRC_DEC_OK; /* downmix only */ |
859 | | |
860 | | /* sanity checks */ |
861 | 0 | if (realBuffer == NULL) return DRC_DEC_NOT_OK; |
862 | 0 | if (reverseInChannelMap == NULL) return DRC_DEC_NOT_OK; |
863 | 0 | if (reverseOutChannelMap == NULL) return DRC_DEC_NOT_OK; |
864 | 0 | if (baseChCnt > 8) return DRC_DEC_NOT_OK; |
865 | 0 | if (baseChCnt != *pNChannels) return DRC_DEC_NOT_OK; |
866 | 0 | if (targetChCnt > 8) return DRC_DEC_NOT_OK; |
867 | | |
868 | 0 | frameSize = drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec); |
869 | |
|
870 | 0 | for (ic = 0; ic < baseChCnt; ic++) { |
871 | 0 | audioChannels[ic] = &(realBuffer[ic * frameSize]); |
872 | 0 | } |
873 | | |
874 | | /* in-place downmix */ |
875 | 0 | for (n = 0; n < frameSize; n++) { |
876 | 0 | for (oc = 0; oc < targetChCnt; oc++) { |
877 | 0 | tmp_out[oc] = (FIXP_DBL)0; |
878 | 0 | for (ic = 0; ic < baseChCnt; ic++) { |
879 | 0 | tmp_out[oc] += |
880 | 0 | fMultDiv2(audioChannels[ic][n], |
881 | 0 | pSelProcOutput->downmixMatrix[reverseInChannelMap[ic]] |
882 | 0 | [reverseOutChannelMap[oc]]) |
883 | 0 | << 3; |
884 | 0 | } |
885 | 0 | } |
886 | 0 | for (oc = 0; oc < targetChCnt; oc++) { |
887 | 0 | if (oc >= baseChCnt) break; |
888 | 0 | audioChannels[oc][n] = tmp_out[oc]; |
889 | 0 | } |
890 | 0 | } |
891 | |
|
892 | 0 | for (oc = targetChCnt; oc < baseChCnt; oc++) { |
893 | 0 | FDKmemset(audioChannels[oc], 0, frameSize * sizeof(FIXP_DBL)); |
894 | 0 | } |
895 | |
|
896 | 0 | *pNChannels = targetChCnt; |
897 | |
|
898 | 0 | return DRC_DEC_OK; |
899 | 0 | } |
900 | | |
901 | | /* Get library info for this module. */ |
902 | | DRC_DEC_ERROR |
903 | 0 | FDK_drcDec_GetLibInfo(LIB_INFO* info) { |
904 | 0 | int i; |
905 | |
|
906 | 0 | if (info == NULL) { |
907 | 0 | return DRC_DEC_INVALID_PARAM; |
908 | 0 | } |
909 | | |
910 | | /* Search for next free tab */ |
911 | 0 | for (i = 0; i < FDK_MODULE_LAST; i++) { |
912 | 0 | if (info[i].module_id == FDK_NONE) break; |
913 | 0 | } |
914 | 0 | if (i == FDK_MODULE_LAST) { |
915 | 0 | return DRC_DEC_NOT_OK; |
916 | 0 | } |
917 | | |
918 | | /* Add the library info */ |
919 | 0 | info[i].module_id = FDK_UNIDRCDEC; |
920 | 0 | info[i].version = LIB_VERSION(DRCDEC_LIB_VL0, DRCDEC_LIB_VL1, DRCDEC_LIB_VL2); |
921 | 0 | LIB_VERSION_STRING(info + i); |
922 | 0 | info[i].build_date = DRCDEC_LIB_BUILD_DATE; |
923 | 0 | info[i].build_time = DRCDEC_LIB_BUILD_TIME; |
924 | 0 | info[i].title = DRCDEC_LIB_TITLE; |
925 | |
|
926 | 0 | return DRC_DEC_OK; |
927 | 0 | } |