1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 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 /**************************** AAC encoder library ******************************
96 
97    Author(s):   V. Bacigalupo
98 
99    Description: Metadata Encoder library interface functions
100 
101 *******************************************************************************/
102 
103 #include "metadata_main.h"
104 #include "metadata_compressor.h"
105 #include "FDK_bitstream.h"
106 #include "FDK_audio.h"
107 #include "genericStds.h"
108 
109 /*----------------- defines ----------------------*/
110 #define MAX_DRC_BANDS (1 << 4)
111 #define MAX_DRC_FRAMELEN (2 * 1024)
112 #define MAX_DELAY_FRAMES (3)
113 
114 /*--------------- structure definitions --------------------*/
115 
116 typedef struct AAC_METADATA {
117   /* MPEG: Dynamic Range Control */
118   struct {
119     UCHAR prog_ref_level_present;
120     SCHAR prog_ref_level;
121 
122     UCHAR dyn_rng_sgn[MAX_DRC_BANDS];
123     UCHAR dyn_rng_ctl[MAX_DRC_BANDS];
124 
125     UCHAR drc_bands_present;
126     UCHAR drc_band_incr;
127     UCHAR drc_band_top[MAX_DRC_BANDS];
128     UCHAR drc_interpolation_scheme;
129     AACENC_METADATA_DRC_PROFILE drc_profile;
130     INT drc_TargetRefLevel; /* used for Limiter */
131 
132     /* excluded channels */
133     UCHAR excluded_chns_present;
134     UCHAR exclude_mask[2]; /* MAX_NUMBER_CHANNELS/8 */
135   } mpegDrc;
136 
137   /* ETSI: addtl ancillary data */
138   struct {
139     /* Heavy Compression */
140     UCHAR compression_on;    /* flag, if compression value should be written */
141     UCHAR compression_value; /* compression value */
142     AACENC_METADATA_DRC_PROFILE comp_profile;
143     INT comp_TargetRefLevel; /* used for Limiter */
144     INT timecode_coarse_status;
145     INT timecode_fine_status;
146 
147     UCHAR extAncDataStatus;
148 
149     struct {
150       UCHAR ext_downmix_lvl_status;
151       UCHAR ext_downmix_gain_status;
152       UCHAR ext_lfe_downmix_status;
153       UCHAR
154       ext_dmix_a_idx; /* extended downmix level (0..7, according to table)
155                        */
156       UCHAR
157       ext_dmix_b_idx; /* extended downmix level (0..7, according to table)
158                        */
159       UCHAR dmx_gain_5_sgn;
160       UCHAR dmx_gain_5_idx;
161       UCHAR dmx_gain_2_sgn;
162       UCHAR dmx_gain_2_idx;
163       UCHAR ext_dmix_lfe_idx; /* extended downmix level for lfe (0..15,
164                                  according to table) */
165 
166     } extAncData;
167 
168   } etsiAncData;
169 
170   SCHAR centerMixLevel; /* center downmix level (0...7, according to table) */
171   SCHAR
172   surroundMixLevel; /* surround downmix level (0...7, according to table) */
173   UCHAR WritePCEMixDwnIdx; /* flag */
174   UCHAR DmxLvl_On;         /* flag */
175 
176   UCHAR dolbySurroundMode;
177   UCHAR drcPresentationMode;
178 
179   UCHAR
180   metadataMode; /* indicate meta data mode in current frame (delay line) */
181 
182 } AAC_METADATA;
183 
184 typedef struct FDK_METADATA_ENCODER {
185   INT metadataMode;
186   HDRC_COMP hDrcComp;
187   AACENC_MetaData submittedMetaData;
188 
189   INT nAudioDataDelay; /* Additional delay to round up to next frame border (in
190                           samples) */
191   INT nMetaDataDelay;  /* Meta data delay (in frames) */
192   INT nChannels;
193   CHANNEL_MODE channelMode;
194 
195   INT_PCM* pAudioDelayBuffer;
196 
197   AAC_METADATA metaDataBuffer[MAX_DELAY_FRAMES];
198   INT metaDataDelayIdx;
199 
200   UCHAR drcInfoPayload[12];
201   UCHAR drcDsePayload[8];
202 
203   INT matrix_mixdown_idx;
204 
205   AACENC_EXT_PAYLOAD exPayload[2];
206   INT nExtensions;
207 
208   UINT maxChannels; /* Maximum number of audio channels to be supported. */
209 
210   INT finalizeMetaData;   /* Delay switch off by one frame and write default
211                              configuration to   finalize the metadata setup. */
212   INT initializeMetaData; /* Fill up delay line with first meta data info. This
213                              is required to have meta data already in first
214                              frame. */
215 } FDK_METADATA_ENCODER;
216 
217 /*---------------- constants -----------------------*/
218 static const AACENC_MetaData defaultMetaDataSetup = {
219     AACENC_METADATA_DRC_NONE,        /* drc_profile */
220     AACENC_METADATA_DRC_NOT_PRESENT, /* comp_profile */
221     -(31 << 16),                     /* drc_TargetRefLevel */
222     -(23 << 16),                     /* comp_TargetRefLevel */
223     0,                               /* prog_ref_level_present */
224     -(23 << 16),                     /* prog_ref_level */
225     0,                               /* PCE_mixdown_idx_present */
226     0,                               /* ETSI_DmxLvl_present */
227     0,                               /* centerMixLevel */
228     0,                               /* surroundMixLevel */
229     0,                               /* dolbySurroundMode */
230     0,                               /* drcPresentationMode */
231     {0, 0, 0, 0, 0, 0, 0, 0, 0}      /* ExtMetaData */
232 };
233 
234 static const FIXP_DBL dmxTable[8] = {
235     ((FIXP_DBL)MAXVAL_DBL), FL2FXCONST_DBL(0.841f), FL2FXCONST_DBL(0.707f),
236     FL2FXCONST_DBL(0.596f), FL2FXCONST_DBL(0.500f), FL2FXCONST_DBL(0.422f),
237     FL2FXCONST_DBL(0.355f), FL2FXCONST_DBL(0.000f)};
238 
239 #define FL2DMXLFE(a) FL2FXCONST_DBL((a) / (1 << LFE_LEV_SCALE))
240 static const FIXP_DBL dmxLfeTable[16] = {
241     FL2DMXLFE(3.162f), FL2DMXLFE(2.000f), FL2DMXLFE(1.679f), FL2DMXLFE(1.413f),
242     FL2DMXLFE(1.189f), FL2DMXLFE(1.000f), FL2DMXLFE(0.841f), FL2DMXLFE(0.707f),
243     FL2DMXLFE(0.596f), FL2DMXLFE(0.500f), FL2DMXLFE(0.316f), FL2DMXLFE(0.178f),
244     FL2DMXLFE(0.100f), FL2DMXLFE(0.032f), FL2DMXLFE(0.010f), FL2DMXLFE(0.000f)};
245 
246 static const UCHAR surmix2matrix_mixdown_idx[8] = {0, 0, 0, 1, 1, 2, 2, 3};
247 
248 /*--------------- function declarations --------------------*/
249 static FDK_METADATA_ERROR WriteMetadataPayload(
250     const HANDLE_FDK_METADATA_ENCODER hMetaData,
251     const AAC_METADATA* const pMetadata);
252 
253 static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata,
254                                         UCHAR* const pExtensionPayload);
255 
256 static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata,
257                                          UCHAR* const pExtensionPayload);
258 
259 static FDK_METADATA_ERROR CompensateAudioDelay(
260     HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples,
261     const UINT audioSamplesBufSize, const INT nAudioSamples);
262 
263 static FDK_METADATA_ERROR LoadSubmittedMetadata(
264     const AACENC_MetaData* const hMetadata, const INT nChannels,
265     const INT metadataMode, AAC_METADATA* const pAacMetaData);
266 
267 static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata,
268                                             HDRC_COMP hDrcComp,
269                                             const INT_PCM* const pSamples,
270                                             const UINT samplesBufSize,
271                                             const INT nSamples);
272 
273 /*------------- function definitions ----------------*/
274 
275 static DRC_PROFILE convertProfile(AACENC_METADATA_DRC_PROFILE aacProfile) {
276   DRC_PROFILE drcProfile = DRC_NONE;
277 
278   switch (aacProfile) {
279     case AACENC_METADATA_DRC_NONE:
280       drcProfile = DRC_NONE;
281       break;
282     case AACENC_METADATA_DRC_FILMSTANDARD:
283       drcProfile = DRC_FILMSTANDARD;
284       break;
285     case AACENC_METADATA_DRC_FILMLIGHT:
286       drcProfile = DRC_FILMLIGHT;
287       break;
288     case AACENC_METADATA_DRC_MUSICSTANDARD:
289       drcProfile = DRC_MUSICSTANDARD;
290       break;
291     case AACENC_METADATA_DRC_MUSICLIGHT:
292       drcProfile = DRC_MUSICLIGHT;
293       break;
294     case AACENC_METADATA_DRC_SPEECH:
295       drcProfile = DRC_SPEECH;
296       break;
297     case AACENC_METADATA_DRC_NOT_PRESENT:
298       drcProfile = DRC_NOT_PRESENT;
299       break;
300     default:
301       drcProfile = DRC_NONE;
302       break;
303   }
304   return drcProfile;
305 }
306 
307 /* convert dialog normalization to program reference level */
308 /* NOTE: this only is correct, if the decoder target level is set to -31dB for
309  * line mode / -20dB for RF mode */
310 static UCHAR dialnorm2progreflvl(const INT d) {
311   return ((UCHAR)fMax(0, fMin((-d + (1 << 13)) >> 14, 127)));
312 }
313 
314 /* convert program reference level to dialog normalization */
315 static INT progreflvl2dialnorm(const UCHAR p) {
316   return -((INT)(p << (16 - 2)));
317 }
318 
319 /* encode downmix levels to Downmixing_levels_MPEG4 */
320 static SCHAR encodeDmxLvls(const SCHAR cmixlev, const SCHAR surmixlev) {
321   SCHAR dmxLvls = 0;
322   dmxLvls |= 0x80 | (cmixlev << 4); /* center_mix_level_on */
323   dmxLvls |= 0x08 | surmixlev;      /* surround_mix_level_on */
324 
325   return dmxLvls;
326 }
327 
328 /* encode AAC DRC gain (ISO/IEC 14496-3:2005  4.5.2.7) */
329 static void encodeDynrng(INT gain, UCHAR* const dyn_rng_ctl,
330                          UCHAR* const dyn_rng_sgn) {
331   if (gain < 0) {
332     *dyn_rng_sgn = 1;
333     gain = -gain;
334   } else {
335     *dyn_rng_sgn = 0;
336   }
337   gain = fMin(gain, (127 << 14));
338 
339   *dyn_rng_ctl = (UCHAR)((gain + (1 << 13)) >> 14);
340 }
341 
342 /* decode AAC DRC gain (ISO/IEC 14496-3:2005  4.5.2.7) */
343 static INT decodeDynrng(const UCHAR dyn_rng_ctl, const UCHAR dyn_rng_sgn) {
344   INT tmp = ((INT)dyn_rng_ctl << (16 - 2));
345   if (dyn_rng_sgn) tmp = -tmp;
346 
347   return tmp;
348 }
349 
350 /* encode AAC compression value (ETSI TS 101 154 page 99) */
351 static UCHAR encodeCompr(INT gain) {
352   UCHAR x, y;
353   INT tmp;
354 
355   /* tmp = (int)((48.164f - gain) / 6.0206f * 15 + 0.5f); */
356   tmp = ((3156476 - gain) * 15 + 197283) / 394566;
357 
358   if (tmp >= 240) {
359     return 0xFF;
360   } else if (tmp < 0) {
361     return 0;
362   } else {
363     x = tmp / 15;
364     y = tmp % 15;
365   }
366 
367   return (x << 4) | y;
368 }
369 
370 /* decode AAC compression value (ETSI TS 101 154 page 99) */
371 static INT decodeCompr(const UCHAR compr) {
372   INT gain;
373   SCHAR x = compr >> 4;     /* 4 MSB of compr */
374   UCHAR y = (compr & 0x0F); /* 4 LSB of compr */
375 
376   /* gain = (INT)((48.164f - 6.0206f * x - 0.4014f * y) ); */
377   gain = (INT)(
378       scaleValue((FIXP_DBL)(((LONG)FL2FXCONST_DBL(6.0206f / 128.f) * (8 - x) -
379                              (LONG)FL2FXCONST_DBL(0.4014f / 128.f) * y)),
380                  -(DFRACT_BITS - 1 - 7 - 16)));
381 
382   return gain;
383 }
384 
385 FDK_METADATA_ERROR FDK_MetadataEnc_Open(HANDLE_FDK_METADATA_ENCODER* phMetaData,
386                                         const UINT maxChannels) {
387   FDK_METADATA_ERROR err = METADATA_OK;
388   HANDLE_FDK_METADATA_ENCODER hMetaData = NULL;
389 
390   if (phMetaData == NULL) {
391     err = METADATA_INVALID_HANDLE;
392     goto bail;
393   }
394 
395   /* allocate memory */
396   if (NULL == (hMetaData = (HANDLE_FDK_METADATA_ENCODER)FDKcalloc(
397                    1, sizeof(FDK_METADATA_ENCODER)))) {
398     err = METADATA_MEMORY_ERROR;
399     goto bail;
400   }
401   FDKmemclear(hMetaData, sizeof(FDK_METADATA_ENCODER));
402 
403   if (NULL == (hMetaData->pAudioDelayBuffer = (INT_PCM*)FDKcalloc(
404                    maxChannels * MAX_DRC_FRAMELEN, sizeof(INT_PCM)))) {
405     err = METADATA_MEMORY_ERROR;
406     goto bail;
407   }
408   FDKmemclear(hMetaData->pAudioDelayBuffer,
409               maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM));
410   hMetaData->maxChannels = maxChannels;
411 
412   /* Allocate DRC Compressor. */
413   if (FDK_DRC_Generator_Open(&hMetaData->hDrcComp) != 0) {
414     err = METADATA_MEMORY_ERROR;
415     goto bail;
416   }
417   hMetaData->channelMode = MODE_UNKNOWN;
418 
419   /* Return metadata instance */
420   *phMetaData = hMetaData;
421 
422   return err;
423 
424 bail:
425   FDK_MetadataEnc_Close(&hMetaData);
426   return err;
427 }
428 
429 FDK_METADATA_ERROR FDK_MetadataEnc_Close(
430     HANDLE_FDK_METADATA_ENCODER* phMetaData) {
431   FDK_METADATA_ERROR err = METADATA_OK;
432 
433   if (phMetaData == NULL) {
434     err = METADATA_INVALID_HANDLE;
435     goto bail;
436   }
437 
438   if (*phMetaData != NULL) {
439     FDK_DRC_Generator_Close(&(*phMetaData)->hDrcComp);
440     FDKfree((*phMetaData)->pAudioDelayBuffer);
441     FDKfree(*phMetaData);
442     *phMetaData = NULL;
443   }
444 bail:
445   return err;
446 }
447 
448 FDK_METADATA_ERROR FDK_MetadataEnc_Init(
449     HANDLE_FDK_METADATA_ENCODER hMetaData, const INT resetStates,
450     const INT metadataMode, const INT audioDelay, const UINT frameLength,
451     const UINT sampleRate, const UINT nChannels, const CHANNEL_MODE channelMode,
452     const CHANNEL_ORDER channelOrder) {
453   FDK_METADATA_ERROR err = METADATA_OK;
454   int i, nFrames, delay;
455 
456   if (hMetaData == NULL) {
457     err = METADATA_INVALID_HANDLE;
458     goto bail;
459   }
460 
461   /* Determine values for delay compensation. */
462   for (nFrames = 0, delay = audioDelay - (INT)frameLength; delay > 0;
463        delay -= (INT)frameLength, nFrames++)
464     ;
465 
466   if ((nChannels > (8)) || (nChannels > hMetaData->maxChannels) ||
467       ((-delay) > MAX_DRC_FRAMELEN) || nFrames >= MAX_DELAY_FRAMES) {
468     err = METADATA_INIT_ERROR;
469     goto bail;
470   }
471 
472   /* Initialize with default setup. */
473   FDKmemcpy(&hMetaData->submittedMetaData, &defaultMetaDataSetup,
474             sizeof(AACENC_MetaData));
475 
476   hMetaData->finalizeMetaData =
477       0; /* finalize meta data only while on/off switching, else disabled */
478   hMetaData->initializeMetaData =
479       0; /* fill up meta data delay line only at a reset otherwise disabled */
480 
481   /* Reset delay lines. */
482   if (resetStates || (hMetaData->nAudioDataDelay != -delay) ||
483       (hMetaData->channelMode != channelMode)) {
484     if (resetStates || (hMetaData->channelMode == MODE_UNKNOWN)) {
485       /* clear delay buffer */
486       FDKmemclear(hMetaData->pAudioDelayBuffer,
487                   hMetaData->maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM));
488     } else {
489       /* if possible, keep static audio channels for seamless channel
490        * reconfiguration */
491       FDK_channelMapDescr mapDescrPrev, mapDescr;
492       int c, src[2] = {-1, -1}, dst[2] = {-1, -1};
493 
494       FDK_chMapDescr_init(&mapDescrPrev, NULL, 0,
495                           (channelOrder == CH_ORDER_MPEG) ? 1 : 0);
496       FDK_chMapDescr_init(&mapDescr, NULL, 0,
497                           (channelOrder == CH_ORDER_MPEG) ? 1 : 0);
498 
499       switch (channelMode) {
500         case MODE_1:
501           if ((INT)nChannels != 2) {
502             /* preserve center channel */
503             src[0] = FDK_chMapDescr_getMapValue(&mapDescrPrev, 0,
504                                                 hMetaData->channelMode);
505             dst[0] = FDK_chMapDescr_getMapValue(&mapDescr, 0, channelMode);
506           }
507           break;
508         case MODE_2:
509         case MODE_1_2:
510         case MODE_1_2_1:
511         case MODE_1_2_2:
512         case MODE_1_2_2_1:
513           if (hMetaData->nChannels >= 2) {
514             /* preserve left/right channel */
515             src[0] = FDK_chMapDescr_getMapValue(
516                 &mapDescrPrev, ((hMetaData->channelMode == 2) ? 0 : 1),
517                 hMetaData->channelMode);
518             src[1] = FDK_chMapDescr_getMapValue(
519                 &mapDescrPrev, ((hMetaData->channelMode == 2) ? 1 : 2),
520                 hMetaData->channelMode);
521             dst[0] = FDK_chMapDescr_getMapValue(
522                 &mapDescr, ((channelMode == 2) ? 0 : 1), channelMode);
523             dst[1] = FDK_chMapDescr_getMapValue(
524                 &mapDescr, ((channelMode == 2) ? 1 : 2), channelMode);
525           }
526           break;
527         default:;
528       }
529       C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, (8));
530       FDKmemclear(scratch_audioDelayBuffer, (8) * sizeof(INT_PCM));
531 
532       i = (hMetaData->nChannels > (INT)nChannels)
533               ? 0
534               : hMetaData->nAudioDataDelay - 1;
535       do {
536         for (c = 0; c < 2; c++) {
537           if (src[c] != -1 && dst[c] != -1) {
538             scratch_audioDelayBuffer[dst[c]] =
539                 hMetaData->pAudioDelayBuffer[i * hMetaData->nChannels + src[c]];
540           }
541         }
542         FDKmemcpy(&hMetaData->pAudioDelayBuffer[i * nChannels],
543                   scratch_audioDelayBuffer, nChannels * sizeof(INT_PCM));
544         i += (hMetaData->nChannels > (INT)nChannels) ? 1 : -1;
545       } while ((i < hMetaData->nAudioDataDelay) && (i >= 0));
546 
547       C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, (8));
548     }
549     FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer));
550     hMetaData->metaDataDelayIdx = 0;
551     hMetaData->initializeMetaData =
552         1; /* fill up delay line with first meta data info */
553   } else {
554     /* Enable meta data. */
555     if ((hMetaData->metadataMode == 0) && (metadataMode != 0)) {
556       /* disable meta data in all delay lines */
557       for (i = 0;
558            i < (int)(sizeof(hMetaData->metaDataBuffer) / sizeof(AAC_METADATA));
559            i++) {
560         LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0,
561                               &hMetaData->metaDataBuffer[i]);
562       }
563     }
564 
565     /* Disable meta data.*/
566     if ((hMetaData->metadataMode != 0) && (metadataMode == 0)) {
567       hMetaData->finalizeMetaData = hMetaData->metadataMode;
568     }
569   }
570 
571   /* Initialize delay. */
572   hMetaData->nAudioDataDelay = -delay;
573   hMetaData->nMetaDataDelay = nFrames;
574   hMetaData->nChannels = nChannels;
575   hMetaData->channelMode = channelMode;
576   hMetaData->metadataMode = metadataMode;
577 
578   /* Initialize compressor. */
579   if ((metadataMode == 1) || (metadataMode == 2)) {
580     if (FDK_DRC_Generator_Initialize(hMetaData->hDrcComp, DRC_NONE, DRC_NONE,
581                                      frameLength, sampleRate, channelMode,
582                                      channelOrder, 1) != 0) {
583       err = METADATA_INIT_ERROR;
584     }
585   }
586 bail:
587   return err;
588 }
589 
590 static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata,
591                                             HDRC_COMP hDrcComp,
592                                             const INT_PCM* const pSamples,
593                                             const UINT samplesBufSize,
594                                             const INT nSamples) {
595   FDK_METADATA_ERROR err = METADATA_OK;
596 
597   INT dynrng, compr;
598   INT dmxGain5, dmxGain2;
599   DRC_PROFILE profileDrc;
600   DRC_PROFILE profileComp;
601 
602   if ((pMetadata == NULL) || (hDrcComp == NULL)) {
603     err = METADATA_INVALID_HANDLE;
604     return err;
605   }
606 
607   profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile);
608   profileComp = convertProfile(pMetadata->etsiAncData.comp_profile);
609 
610   /* first, check if profile is same as last frame
611    * otherwise, update setup */
612   if ((profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp)) ||
613       (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp))) {
614     FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp);
615   }
616 
617   /* Sanity check */
618   if (profileComp == DRC_NONE) {
619     pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external
620                                                         values will be written
621                                                         if not configured */
622   }
623 
624   /* in case of embedding external values, copy this now (limiter may overwrite
625    * them) */
626   dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0],
627                         pMetadata->mpegDrc.dyn_rng_sgn[0]);
628   compr = decodeCompr(pMetadata->etsiAncData.compression_value);
629 
630   dmxGain5 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_5_idx,
631                           pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn);
632   dmxGain2 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_2_idx,
633                           pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn);
634 
635   /* Call compressor */
636   if (FDK_DRC_Generator_Calc(
637           hDrcComp, pSamples, samplesBufSize,
638           progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level),
639           pMetadata->mpegDrc.drc_TargetRefLevel,
640           pMetadata->etsiAncData.comp_TargetRefLevel,
641           dmxTable[pMetadata->centerMixLevel],
642           dmxTable[pMetadata->surroundMixLevel],
643           dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_a_idx],
644           dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_b_idx],
645           pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status
646               ? dmxLfeTable[pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx]
647               : (FIXP_DBL)0,
648           dmxGain5, dmxGain2, &dynrng, &compr) != 0) {
649     err = METADATA_ENCODE_ERROR;
650     goto bail;
651   }
652 
653   /* Write DRC values */
654   pMetadata->mpegDrc.drc_band_incr = 0;
655   encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl,
656                pMetadata->mpegDrc.dyn_rng_sgn);
657   pMetadata->etsiAncData.compression_value = encodeCompr(compr);
658 
659 bail:
660   return err;
661 }
662 
663 FDK_METADATA_ERROR FDK_MetadataEnc_Process(
664     HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples,
665     const UINT audioSamplesBufSize, const INT nAudioSamples,
666     const AACENC_MetaData* const pMetadata,
667     AACENC_EXT_PAYLOAD** ppMetaDataExtPayload, UINT* nMetaDataExtensions,
668     INT* matrix_mixdown_idx) {
669   FDK_METADATA_ERROR err = METADATA_OK;
670   int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode;
671 
672   /* Where to write new meta data info */
673   metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx;
674 
675   /* How to write the data */
676   metadataMode = hMetaDataEnc->metadataMode;
677 
678   /* Compensate meta data delay. */
679   hMetaDataEnc->metaDataDelayIdx++;
680   if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay)
681     hMetaDataEnc->metaDataDelayIdx = 0;
682 
683   /* Where to read pending meta data info from. */
684   metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx;
685 
686   /* Submit new data if available. */
687   if (pMetadata != NULL) {
688     FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata,
689               sizeof(AACENC_MetaData));
690   }
691 
692   /* Write one additional frame with default configuration of meta data. Ensure
693    * defined behaviour on decoder side. */
694   if ((hMetaDataEnc->finalizeMetaData != 0) &&
695       (hMetaDataEnc->metadataMode == 0)) {
696     FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup,
697               sizeof(AACENC_MetaData));
698     metadataMode = hMetaDataEnc->finalizeMetaData;
699     hMetaDataEnc->finalizeMetaData = 0;
700   }
701 
702   /* Get last submitted data. */
703   if ((err = LoadSubmittedMetadata(
704            &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels,
705            metadataMode,
706            &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) !=
707       METADATA_OK) {
708     goto bail;
709   }
710 
711   /* Calculate compressor if necessary and updata meta data info */
712   if ((hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 1) ||
713       (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 2)) {
714     if ((err = ProcessCompressor(
715              &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx],
716              hMetaDataEnc->hDrcComp, pAudioSamples, audioSamplesBufSize,
717              nAudioSamples)) != METADATA_OK) {
718       /* Get last submitted data again. */
719       LoadSubmittedMetadata(
720           &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels,
721           metadataMode, &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]);
722     }
723   }
724 
725   /* Fill up delay line with initial meta data info.*/
726   if ((hMetaDataEnc->initializeMetaData != 0) &&
727       (hMetaDataEnc->metadataMode != 0)) {
728     int i;
729     for (i = 0;
730          i < (int)(sizeof(hMetaDataEnc->metaDataBuffer) / sizeof(AAC_METADATA));
731          i++) {
732       if (i != metaDataDelayWriteIdx) {
733         FDKmemcpy(&hMetaDataEnc->metaDataBuffer[i],
734                   &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx],
735                   sizeof(hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]));
736       }
737     }
738     hMetaDataEnc->initializeMetaData = 0;
739   }
740 
741   /* Convert Meta Data side info to bitstream data. */
742   FDK_ASSERT(metaDataDelayReadIdx < MAX_DELAY_FRAMES);
743   if ((err = WriteMetadataPayload(
744            hMetaDataEnc,
745            &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) !=
746       METADATA_OK) {
747     goto bail;
748   }
749 
750   /* Assign meta data to output */
751   *ppMetaDataExtPayload = hMetaDataEnc->exPayload;
752   *nMetaDataExtensions = hMetaDataEnc->nExtensions;
753   *matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx;
754 
755 bail:
756   /* Compensate audio delay, reset err status. */
757   err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, audioSamplesBufSize,
758                              nAudioSamples / hMetaDataEnc->nChannels);
759 
760   return err;
761 }
762 
763 static FDK_METADATA_ERROR CompensateAudioDelay(
764     HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples,
765     const UINT audioSamplesBufSize, const INT nAudioSamples) {
766   FDK_METADATA_ERROR err = METADATA_OK;
767 
768   if (hMetaDataEnc->nAudioDataDelay) {
769     C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, 1024);
770 
771     for (int c = 0; c < hMetaDataEnc->nChannels; c++) {
772       int M = 1024;
773       INT_PCM* pAudioSamples2 = pAudioSamples + c * audioSamplesBufSize;
774       int delayIdx = hMetaDataEnc->nAudioDataDelay;
775 
776       do {
777         M = fMin(M, delayIdx);
778         delayIdx -= M;
779 
780         FDKmemcpy(&scratch_audioDelayBuffer[0],
781                   &pAudioSamples2[(nAudioSamples - M)], sizeof(INT_PCM) * M);
782         FDKmemmove(&pAudioSamples2[M], &pAudioSamples2[0],
783                    sizeof(INT_PCM) * (nAudioSamples - M));
784         FDKmemcpy(
785             &pAudioSamples2[0],
786             &hMetaDataEnc->pAudioDelayBuffer[delayIdx +
787                                              c * hMetaDataEnc->nAudioDataDelay],
788             sizeof(INT_PCM) * M);
789         FDKmemcpy(
790             &hMetaDataEnc->pAudioDelayBuffer[delayIdx +
791                                              c * hMetaDataEnc->nAudioDataDelay],
792             &scratch_audioDelayBuffer[0], sizeof(INT_PCM) * M);
793 
794       } while (delayIdx > 0);
795     }
796 
797     C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, 1024);
798   }
799 
800   return err;
801 }
802 
803 /*-----------------------------------------------------------------------------
804 
805   functionname: WriteMetadataPayload
806   description:  fills anc data and extension payload
807   returns:      Error status
808 
809  ------------------------------------------------------------------------------*/
810 static FDK_METADATA_ERROR WriteMetadataPayload(
811     const HANDLE_FDK_METADATA_ENCODER hMetaData,
812     const AAC_METADATA* const pMetadata) {
813   FDK_METADATA_ERROR err = METADATA_OK;
814 
815   if ((hMetaData == NULL) || (pMetadata == NULL)) {
816     err = METADATA_INVALID_HANDLE;
817     goto bail;
818   }
819 
820   hMetaData->nExtensions = 0;
821   hMetaData->matrix_mixdown_idx = -1;
822 
823   if (pMetadata->metadataMode != 0) {
824     /* AAC-DRC */
825     if ((pMetadata->metadataMode == 1) || (pMetadata->metadataMode == 2)) {
826       hMetaData->exPayload[hMetaData->nExtensions].pData =
827           hMetaData->drcInfoPayload;
828       hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE;
829       hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1;
830 
831       hMetaData->exPayload[hMetaData->nExtensions].dataSize =
832           WriteDynamicRangeInfoPayload(
833               pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData);
834 
835       hMetaData->nExtensions++;
836     } /* pMetadata->metadataMode==1 || pMetadata->metadataMode==2 */
837 
838     /* Matrix Mixdown Coefficient in PCE */
839     if (pMetadata->WritePCEMixDwnIdx) {
840       hMetaData->matrix_mixdown_idx =
841           surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel];
842     }
843 
844     /* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */
845     if ((pMetadata->metadataMode == 2) ||
846         (pMetadata->metadataMode == 3)) /* MP4_METADATA_MPEG_ETSI */
847     {
848       hMetaData->exPayload[hMetaData->nExtensions].pData =
849           hMetaData->drcDsePayload;
850       hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT;
851       hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1;
852 
853       hMetaData->exPayload[hMetaData->nExtensions].dataSize =
854           WriteEtsiAncillaryDataPayload(
855               pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData);
856 
857       hMetaData->nExtensions++;
858     } /* metadataMode==2 || metadataMode==3 */
859 
860   } /* metadataMode != 0 */
861 
862 bail:
863   return err;
864 }
865 
866 static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata,
867                                         UCHAR* const pExtensionPayload) {
868   const INT pce_tag_present = 0; /* yet fixed setting! */
869   const INT prog_ref_lev_res_bits = 0;
870   INT i, drc_num_bands = 1;
871 
872   FDK_BITSTREAM bsWriter;
873   FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER);
874 
875   /* dynamic_range_info() */
876   FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */
877   if (pce_tag_present) {
878     FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */
879     FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */
880   }
881 
882   /* Exclude channels */
883   FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0,
884                1); /* excluded_chns_present*/
885 
886   /* Multiband DRC */
887   FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0,
888                1); /* drc_bands_present */
889   if (pMetadata->mpegDrc.drc_bands_present) {
890     FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr,
891                  4); /* drc_band_incr */
892     FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme,
893                  4); /* drc_interpolation_scheme */
894     drc_num_bands += pMetadata->mpegDrc.drc_band_incr;
895     for (i = 0; i < drc_num_bands; i++) {
896       FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_top[i],
897                    8); /* drc_band_top */
898     }
899   }
900 
901   /* Program Reference Level */
902   FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present,
903                1); /* prog_ref_level_present */
904   if (pMetadata->mpegDrc.prog_ref_level_present) {
905     FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level,
906                  7); /* prog_ref_level */
907     FDKwriteBits(&bsWriter, prog_ref_lev_res_bits,
908                  1); /* prog_ref_level_reserved_bits */
909   }
910 
911   /* DRC Values */
912   for (i = 0; i < drc_num_bands; i++) {
913     FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.dyn_rng_sgn[i]) ? 1 : 0,
914                  1); /* dyn_rng_sgn[ */
915     FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i],
916                  7); /* dyn_rng_ctl */
917   }
918 
919   /* return number of valid bits in extension payload. */
920   return FDKgetValidBits(&bsWriter);
921 }
922 
923 static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata,
924                                          UCHAR* const pExtensionPayload) {
925   FDK_BITSTREAM bsWriter;
926   FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER);
927 
928   /* ancillary_data_sync */
929   FDKwriteBits(&bsWriter, 0xBC, 8);
930 
931   /* bs_info */
932   FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */
933   FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode,
934                2); /* dolby_surround_mode */
935   FDKwriteBits(&bsWriter, pMetadata->drcPresentationMode,
936                2);                 /* DRC presentation mode */
937   FDKwriteBits(&bsWriter, 0x0, 1); /* stereo_downmix_mode */
938   FDKwriteBits(&bsWriter, 0x0, 1); /* reserved */
939 
940   /* ancillary_data_status */
941   FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */
942   FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0,
943                1); /* downmixing_levels_MPEG4_status */
944   FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncDataStatus,
945                1); /* ext_anc_data_status */
946   FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0,
947                1); /* audio_coding_mode_and_compression status */
948   FDKwriteBits(&bsWriter,
949                (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0,
950                1); /* coarse_grain_timecode_status */
951   FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0,
952                1); /* fine_grain_timecode_status */
953 
954   /* downmixing_levels_MPEG4_status */
955   if (pMetadata->DmxLvl_On) {
956     FDKwriteBits(
957         &bsWriter,
958         encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel),
959         8);
960   }
961 
962   /* audio_coding_mode_and_compression_status */
963   if (pMetadata->etsiAncData.compression_on) {
964     FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */
965     FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value,
966                  8); /* compression value */
967   }
968 
969   /* grain-timecode coarse/fine */
970   if (pMetadata->etsiAncData.timecode_coarse_status) {
971     FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */
972   }
973 
974   if (pMetadata->etsiAncData.timecode_fine_status) {
975     FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */
976   }
977 
978   /* extended ancillary data structure */
979   if (pMetadata->etsiAncData.extAncDataStatus) {
980     /* ext_ancillary_data_status */
981     FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
982     FDKwriteBits(&bsWriter,
983                  pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status,
984                  1); /* ext_downmixing_levels_status */
985     FDKwriteBits(&bsWriter,
986                  pMetadata->etsiAncData.extAncData.ext_downmix_gain_status,
987                  1); /* ext_downmixing_global_gains_status */
988     FDKwriteBits(&bsWriter,
989                  pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status,
990                  1);               /* ext_downmixing_lfe_level_status" */
991     FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */
992 
993     /* ext_downmixing_levels */
994     if (pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status) {
995       FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_a_idx,
996                    3); /* dmix_a_idx */
997       FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_b_idx,
998                    3);               /* dmix_b_idx */
999       FDKwriteBits(&bsWriter, 0, 2); /* Reserved, set to "0" */
1000     }
1001 
1002     /* ext_downmixing_gains */
1003     if (pMetadata->etsiAncData.extAncData.ext_downmix_gain_status) {
1004       FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn,
1005                    1); /* dmx_gain_5_sign */
1006       FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_idx,
1007                    6);               /* dmx_gain_5_idx */
1008       FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
1009       FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn,
1010                    1); /* dmx_gain_2_sign */
1011       FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_idx,
1012                    6);               /* dmx_gain_2_idx */
1013       FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
1014     }
1015 
1016     if (pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status) {
1017       FDKwriteBits(&bsWriter,
1018                    pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx,
1019                    4);               /* dmix_lfe_idx */
1020       FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */
1021     }
1022   }
1023 
1024   return FDKgetValidBits(&bsWriter);
1025 }
1026 
1027 static FDK_METADATA_ERROR LoadSubmittedMetadata(
1028     const AACENC_MetaData* const hMetadata, const INT nChannels,
1029     const INT metadataMode, AAC_METADATA* const pAacMetaData) {
1030   FDK_METADATA_ERROR err = METADATA_OK;
1031 
1032   if (pAacMetaData == NULL) {
1033     err = METADATA_INVALID_HANDLE;
1034   } else {
1035     /* init struct */
1036     FDKmemclear(pAacMetaData, sizeof(AAC_METADATA));
1037 
1038     if (hMetadata != NULL) {
1039       /* convert data */
1040       pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile;
1041       pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile;
1042       pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel;
1043       pAacMetaData->etsiAncData.comp_TargetRefLevel =
1044           hMetadata->comp_TargetRefLevel;
1045       pAacMetaData->mpegDrc.prog_ref_level_present =
1046           hMetadata->prog_ref_level_present;
1047       pAacMetaData->mpegDrc.prog_ref_level =
1048           dialnorm2progreflvl(hMetadata->prog_ref_level);
1049 
1050       pAacMetaData->centerMixLevel = hMetadata->centerMixLevel;
1051       pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel;
1052       pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present;
1053       pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present;
1054 
1055       pAacMetaData->etsiAncData.compression_on =
1056           (hMetadata->comp_profile == AACENC_METADATA_DRC_NOT_PRESENT ? 0 : 1);
1057 
1058       if (pAacMetaData->mpegDrc.drc_profile ==
1059           AACENC_METADATA_DRC_NOT_PRESENT) {
1060         pAacMetaData->mpegDrc.drc_profile =
1061             AACENC_METADATA_DRC_NONE; /* MPEG DRC gains are
1062                                          always present in BS
1063                                          syntax */
1064         /* we should give a warning, but ErrorHandler does not support this */
1065       }
1066 
1067       if (nChannels == 2) {
1068         pAacMetaData->dolbySurroundMode =
1069             hMetadata->dolbySurroundMode; /* dolby_surround_mode */
1070       } else {
1071         pAacMetaData->dolbySurroundMode = 0;
1072       }
1073 
1074       pAacMetaData->drcPresentationMode = hMetadata->drcPresentationMode;
1075       /* override external values if DVB DRC presentation mode is given */
1076       if (pAacMetaData->drcPresentationMode == 1) {
1077         pAacMetaData->mpegDrc.drc_TargetRefLevel =
1078             fMax(-(31 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel);
1079         pAacMetaData->etsiAncData.comp_TargetRefLevel = fMax(
1080             -(20 << 16),
1081             pAacMetaData->etsiAncData.comp_TargetRefLevel); /* implies -23dB */
1082       }
1083       if (pAacMetaData->drcPresentationMode == 2) {
1084         pAacMetaData->mpegDrc.drc_TargetRefLevel =
1085             fMax(-(23 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel);
1086         pAacMetaData->etsiAncData.comp_TargetRefLevel =
1087             fMax(-(23 << 16), pAacMetaData->etsiAncData.comp_TargetRefLevel);
1088       }
1089       if (pAacMetaData->etsiAncData.comp_profile ==
1090           AACENC_METADATA_DRC_NOT_PRESENT) {
1091         /* DVB defines to revert to Light DRC if heavy is not present */
1092         if (pAacMetaData->drcPresentationMode != 0) {
1093           /* we exclude the "not indicated" mode as this requires the user to
1094            * define desired levels anyway */
1095           pAacMetaData->mpegDrc.drc_TargetRefLevel =
1096               fMax(pAacMetaData->etsiAncData.comp_TargetRefLevel,
1097                    pAacMetaData->mpegDrc.drc_TargetRefLevel);
1098         }
1099       }
1100 
1101       pAacMetaData->etsiAncData.timecode_coarse_status =
1102           0; /* not yet supported - attention: Update
1103                 GetEstMetadataBytesPerFrame() if enable this! */
1104       pAacMetaData->etsiAncData.timecode_fine_status =
1105           0; /* not yet supported - attention: Update
1106                 GetEstMetadataBytesPerFrame() if enable this! */
1107 
1108       /* extended ancillary data */
1109       pAacMetaData->etsiAncData.extAncDataStatus =
1110           ((hMetadata->ExtMetaData.extAncDataEnable == 1) ? 1 : 0);
1111 
1112       if (pAacMetaData->etsiAncData.extAncDataStatus) {
1113         pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status =
1114             (hMetadata->ExtMetaData.extDownmixLevelEnable ? 1 : 0);
1115         pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status =
1116             (hMetadata->ExtMetaData.dmxGainEnable ? 1 : 0);
1117         pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status =
1118             (hMetadata->ExtMetaData.lfeDmxEnable ? 1 : 0);
1119 
1120         pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx =
1121             hMetadata->ExtMetaData.extDownmixLevel_A;
1122         pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx =
1123             hMetadata->ExtMetaData.extDownmixLevel_B;
1124 
1125         if (pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status) {
1126           encodeDynrng(hMetadata->ExtMetaData.dmxGain5,
1127                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx),
1128                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn));
1129           encodeDynrng(hMetadata->ExtMetaData.dmxGain2,
1130                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx),
1131                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn));
1132         } else {
1133           encodeDynrng(1 << 16,
1134                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx),
1135                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn));
1136           encodeDynrng(1 << 16,
1137                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx),
1138                        &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn));
1139         }
1140 
1141         if (pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status) {
1142           pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx =
1143               hMetadata->ExtMetaData.lfeDmxLevel;
1144         } else {
1145           pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx =
1146               15; /* -inf dB */
1147         }
1148       } else {
1149         pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = 0;
1150         pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = 0;
1151         pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = 0;
1152 
1153         pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = 7; /* -inf dB */
1154         pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = 7; /* -inf dB */
1155 
1156         encodeDynrng(1 << 16,
1157                      &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx),
1158                      &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn));
1159         encodeDynrng(1 << 16,
1160                      &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx),
1161                      &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn));
1162 
1163         pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx =
1164             15; /* -inf dB */
1165       }
1166 
1167       pAacMetaData->metadataMode = metadataMode;
1168     } else {
1169       pAacMetaData->metadataMode = 0; /* there is no configuration available */
1170     }
1171   }
1172 
1173   return err;
1174 }
1175 
1176 INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc) {
1177   INT delay = 0;
1178 
1179   if (hMetadataEnc != NULL) {
1180     delay = hMetadataEnc->nAudioDataDelay;
1181   }
1182 
1183   return delay;
1184 }
1185