1603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 2603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* ----------------------------------------------------------------------------------------------------------- 3603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviSoftware License for The Fraunhofer FDK AAC Codec Library for Android 4603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 5603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi� Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V. 6603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi All rights reserved. 7603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 8603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 1. INTRODUCTION 9603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviThe Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements 10603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivithe MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. 11603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviThis FDK AAC Codec software is intended to be used on a wide variety of Android devices. 12603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 13603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviAAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual 14603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviaudio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by 15603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviindependent studies and is widely deployed. AAC has been standardized by ISO and IEC as part 16603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviof the MPEG specifications. 17603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 18603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviPatent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) 19603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivimay be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners 20603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviindividually for the purpose of encoding or decoding bit streams in products that are compliant with 21603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivithe ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license 22603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivithese patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec 23603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivisoftware may already be covered under those patent licenses when it is used for those licensed purposes only. 24603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 25603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviCommercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, 26603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviare also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional 27603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviapplications information and documentation. 28603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 29603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi2. COPYRIGHT LICENSE 30603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 31603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviRedistribution and use in source and binary forms, with or without modification, are permitted without 32603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivipayment of copyright license fees provided that you satisfy the following conditions: 33603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 34603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviYou must retain the complete text of this software license in redistributions of the FDK AAC Codec or 35603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviyour modifications thereto in source code form. 36603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 37603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviYou must retain the complete text of this software license in the documentation and/or other materials 38603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviprovided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. 39603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviYou must make available free of charge copies of the complete source code of the FDK AAC Codec and your 40603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivimodifications thereto to recipients of copies in binary form. 41603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 42603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviThe name of Fraunhofer may not be used to endorse or promote products derived from this library without 43603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviprior written permission. 44603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 45603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviYou may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec 46603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivisoftware or your modifications thereto. 47603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 48603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviYour modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software 49603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviand the date of any change. For modified versions of the FDK AAC Codec, the term 50603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term 51603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." 52603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 53603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi3. NO PATENT LICENSE 54603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 55603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviNO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, 56603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with 57603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivirespect to this software. 58603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 59603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviYou may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized 60603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviby appropriate patent licenses. 61603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 62603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi4. DISCLAIMER 63603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 64603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviThis FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors 65603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties 66603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviof merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 67603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviCONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, 68603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviincluding but not limited to procurement of substitute goods or services; loss of use, data, or profits, 69603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivior business interruption, however caused and on any theory of liability, whether in contract, strict 70603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviliability, or tort (including negligence), arising in any way out of the use of this software, even if 71603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviadvised of the possibility of such damage. 72603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 73603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi5. CONTACT INFORMATION 74603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 75603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviFraunhofer Institute for Integrated Circuits IIS 76603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviAttention: Audio and Multimedia Departments - FDK AAC LL 77603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviAm Wolfsmantel 33 78603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi91058 Erlangen, Germany 79603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 80603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviwww.iis.fraunhofer.de/amm 81603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviamm-info@iis.fraunhofer.de 82603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi----------------------------------------------------------------------------------------------------------- */ 83603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 84603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/************************ FDK PCM postprocessor module ********************* 85603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 86603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi Author(s): Matthias Neusinger 87603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi Description: Hard limiter for clipping prevention 88603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 89603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi*******************************************************************************/ 90603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 91603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi#include "limiter.h" 92603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 93603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 94603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivistruct TDLimiter { 95603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int attack; 96603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL attackConst, releaseConst; 97603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int attackMs, releaseMs, maxAttackMs; 98603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_PCM threshold; 99603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int channels, maxChannels; 100603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int sampleRate, maxSampleRate; 101603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL cor, max; 102603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL* maxBuf; 103603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL* delayBuf; 104603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int maxBufIdx, delayBufIdx; 105603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL smoothState0; 106603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL minGain; 107603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 108603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL additionalGainPrev; 109603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL additionalGainFilterState; 110603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL additionalGainFilterState1; 111603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi}; 112603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 113603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* create limiter */ 114603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLimiterPtr createLimiter( 115603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int maxAttackMs, 116603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int releaseMs, 117603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi INT_PCM threshold, 118603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int maxChannels, 119603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int maxSampleRate 120603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi ) 121603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 122603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi TDLimiterPtr limiter = NULL; 123603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int attack, release; 124603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL attackConst, releaseConst, exponent; 125603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi INT e_ans; 126603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 127603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* calc attack and release time in samples */ 128603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000); 129603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi release = (unsigned int)(releaseMs * maxSampleRate / 1000); 130603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 131603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* alloc limiter struct */ 132603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter)); 133603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (!limiter) return NULL; 134603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 135603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* alloc max and delay buffers */ 136603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL)); 137603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->delayBuf = (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL)); 138603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 139603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (!limiter->maxBuf || !limiter->delayBuf) { 140603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi destroyLimiter(limiter); 141603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return NULL; 142603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 143603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 144603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ 145603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi exponent = invFixp(attack+1); 146603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); 147603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attackConst = scaleValue(attackConst, e_ans); 148603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 149603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ 150603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi exponent = invFixp(release + 1); 151603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); 152603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi releaseConst = scaleValue(releaseConst, e_ans); 153603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 154603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* init parameters */ 155603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attackMs = maxAttackMs; 156603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->maxAttackMs = maxAttackMs; 157603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->releaseMs = releaseMs; 158603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attack = attack; 159603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attackConst = attackConst; 160603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->releaseConst = releaseConst; 161603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->threshold = (FIXP_PCM)threshold; 162603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->channels = maxChannels; 163603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->maxChannels = maxChannels; 164603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->sampleRate = maxSampleRate; 165603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->maxSampleRate = maxSampleRate; 166603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 167603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi resetLimiter(limiter); 168603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 169603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return limiter; 170603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 171603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 172603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 173603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* reset limiter */ 174603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR resetLimiter(TDLimiterPtr limiter) 175603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 176603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (limiter != NULL) { 177603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 178603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->maxBufIdx = 0; 179603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->delayBufIdx = 0; 180603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->max = (FIXP_DBL)0; 181603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->cor = FL2FXCONST_DBL(1.0f/(1<<1)); 182603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->smoothState0 = FL2FXCONST_DBL(1.0f/(1<<1)); 183603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->minGain = FL2FXCONST_DBL(1.0f/(1<<1)); 184603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 185603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->additionalGainPrev = FL2FXCONST_DBL(1.0f/(1<<TDL_GAIN_SCALING)); 186603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->additionalGainFilterState = FL2FXCONST_DBL(1.0f/(1<<TDL_GAIN_SCALING)); 187603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->additionalGainFilterState1 = FL2FXCONST_DBL(1.0f/(1<<TDL_GAIN_SCALING)); 188603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 189603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL) ); 190603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDKmemset(limiter->delayBuf, 0, limiter->attack * limiter->channels * sizeof(FIXP_DBL) ); 191603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 192603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else { 193603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_INVALID_HANDLE; 194603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 195603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 196603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 197603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 198603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 199603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 200603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* destroy limiter */ 201603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR destroyLimiter(TDLimiterPtr limiter) 202603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 203603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (limiter != NULL) { 204603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDKfree(limiter->maxBuf); 205603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDKfree(limiter->delayBuf); 206603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 207603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDKfree(limiter); 208603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 209603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else { 210603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_INVALID_HANDLE; 211603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 212603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 213603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 214603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 215603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* apply limiter */ 216603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR applyLimiter(TDLimiterPtr limiter, 217603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi INT_PCM* samples, 218603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL* pGain, 219603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi const INT* gain_scale, 220603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi const UINT gain_size, 221603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi const UINT gain_delay, 222603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi const UINT nSamples) 223603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 224603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int i, j; 225603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_PCM tmp1, tmp2; 226603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL tmp, old, gain, additionalGain, additionalGainUnfiltered; 227603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL minGain = FL2FXCONST_DBL(1.0f/(1<<1)); 228603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 229603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDK_ASSERT(gain_size == 1); 230603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDK_ASSERT(gain_delay <= nSamples); 231603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 232603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; 233603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 234603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi { 235603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int channels = limiter->channels; 236603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int attack = limiter->attack; 237603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL attackConst = limiter->attackConst; 238603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL releaseConst = limiter->releaseConst; 239603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL threshold = FX_PCM2FX_DBL(limiter->threshold)>>TDL_GAIN_SCALING; 240603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 241603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL max = limiter->max; 242603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL* maxBuf = limiter->maxBuf; 243603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int maxBufIdx = limiter->maxBufIdx; 244603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL cor = limiter->cor; 245603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL* delayBuf = limiter->delayBuf; 246603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int delayBufIdx = limiter->delayBufIdx; 247603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 248603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL smoothState0 = limiter->smoothState0; 249603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState; 250603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1; 251603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 252603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi for (i = 0; i < nSamples; i++) { 253603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 254603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (i < gain_delay) { 255603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGainUnfiltered = limiter->additionalGainPrev; 256603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } else { 257603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGainUnfiltered = pGain[0]; 258603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 259603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 260603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* Smooth additionalGain */ 261603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* [b,a] = butter(1, 0.01) */ 262603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi static const FIXP_SGL b[] = { FL2FXCONST_SGL(0.015466*2.0), FL2FXCONST_SGL( 0.015466*2.0) }; 263603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi static const FIXP_SGL a[] = { FL2FXCONST_SGL(1.000000), FL2FXCONST_SGL(-0.96907) }; 264603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* [b,a] = butter(1, 0.001) */ 265603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi //static const FIXP_SGL b[] = { FL2FXCONST_SGL(0.0015683*2.0), FL2FXCONST_SGL( 0.0015683*2.0) }; 266603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi //static const FIXP_SGL a[] = { FL2FXCONST_SGL(1.0000000), FL2FXCONST_SGL(-0.99686) }; 267603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGain = - fMult(additionalGainSmoothState, a[1]) + fMultDiv2( additionalGainUnfiltered, b[0]) + fMultDiv2(additionalGainSmoothState1, b[1]); 268603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGainSmoothState1 = additionalGainUnfiltered; 269603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGainSmoothState = additionalGain; 270603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 271603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* Apply the additional scaling that has no delay and no smoothing */ 272603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (gain_scale[0] > 0) { 273603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGain <<= gain_scale[0]; 274603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } else { 275603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi additionalGain >>= gain_scale[0]; 276603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 277603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 278603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* get maximum absolute sample value of all channels, including the additional gain. */ 279603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp1 = (FIXP_PCM)0; 280603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi for (j = 0; j < channels; j++) { 281603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp2 = (FIXP_PCM)samples[i * channels + j]; 282603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (tmp2 == (FIXP_PCM)SAMPLE_MIN) /* protect fAbs from -1.0 value */ 283603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp2 = (FIXP_PCM)(SAMPLE_MIN+1); 284603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp1 = fMax(tmp1, fAbs(tmp2)); 285603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 286603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp = SATURATE_LEFT_SHIFT(fMultDiv2(tmp1, additionalGain), 1, DFRACT_BITS); 287603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 288603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* set threshold as lower border to save calculations in running maximum algorithm */ 289603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp = fMax(tmp, threshold); 290603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 291603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* running maximum */ 292603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi old = maxBuf[maxBufIdx]; 293603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi maxBuf[maxBufIdx] = tmp; 294603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 295603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (tmp >= max) { 296603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* new sample is greater than old maximum, so it is the new maximum */ 297603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi max = tmp; 298603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 299603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else if (old < max) { 300603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* maximum does not change, as the sample, which has left the window was 301603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi not the maximum */ 302603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 303603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else { 304603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* the old maximum has left the window, we have to search the complete 305603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi buffer for the new max */ 306603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi max = maxBuf[0]; 307603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi for (j = 1; j <= attack; j++) { 308603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (maxBuf[j] > max) max = maxBuf[j]; 309603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 310603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 311603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi maxBufIdx++; 312603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (maxBufIdx >= attack+1) maxBufIdx = 0; 313603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 314603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* calc gain */ 315603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* gain is downscaled by one, so that gain = 1.0 can be represented */ 316603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (max > threshold) { 317603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi gain = fDivNorm(threshold, max)>>1; 318603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 319603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else { 320603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi gain = FL2FXCONST_DBL(1.0f/(1<<1)); 321603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 322603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 323603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* gain smoothing, method: TDL_EXPONENTIAL */ 324603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* first order IIR filter with attack correction to avoid overshoots */ 325603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 326603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* correct the 'aiming' value of the exponential attack to avoid the remaining overshoot */ 327603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (gain < smoothState0) { 328603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi cor = fMin(cor, fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f*(1<<1)),smoothState0)), FL2FXCONST_SGL(1.11111111f/(1<<1)))<<2); 329603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 330603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else { 331603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi cor = gain; 332603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 333603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 334603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* smoothing filter */ 335603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (cor < smoothState0) { 336603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi smoothState0 = fMult(attackConst,(smoothState0 - cor)) + cor; /* attack */ 337603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */ 338603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 339603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi else { 340603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* sign inversion twice to round towards +infinity, 341603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi so that gain can converge to 1.0 again, 342603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi for bit-identical output when limiter is not active */ 343603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi smoothState0 = -fMult(releaseConst,-(smoothState0 - cor)) + cor; /* release */ 344603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 345603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 346603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi gain = smoothState0; 347603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 348603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* lookahead delay, apply gain */ 349603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi for (j = 0; j < channels; j++) { 350603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 351603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp = delayBuf[delayBufIdx * channels + j]; 352603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi delayBuf[delayBufIdx * channels + j] = fMult((FIXP_PCM)samples[i * channels + j], additionalGain); 353603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 354603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* Apply gain to delayed signal */ 355603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (gain < FL2FXCONST_DBL(1.0f/(1<<1))) 356603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi tmp = fMult(tmp,gain<<1); 357603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 358603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi samples[i * channels + j] = FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(tmp,TDL_GAIN_SCALING,DFRACT_BITS)); 359603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 360603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi delayBufIdx++; 361603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (delayBufIdx >= attack) delayBufIdx = 0; 362603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 363603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* save minimum gain factor */ 364603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (gain < minGain) minGain = gain; 365603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 366603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 367603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 368603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->max = max; 369603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->maxBufIdx = maxBufIdx; 370603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->cor = cor; 371603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->delayBufIdx = delayBufIdx; 372603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 373603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->smoothState0 = smoothState0; 374603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->additionalGainFilterState = additionalGainSmoothState; 375603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->additionalGainFilterState1 = additionalGainSmoothState1; 376603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 377603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->minGain = minGain; 378603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 379603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->additionalGainPrev = pGain[0]; 380603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 381603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 382603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi } 383603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 384603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 385603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* get delay in samples */ 386603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Triviunsigned int getLimiterDelay(TDLimiterPtr limiter) 387603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 388603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FDK_ASSERT(limiter != NULL); 389603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return limiter->attack; 390603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 391603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 392603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* set number of channels */ 393603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR setLimiterNChannels(TDLimiterPtr limiter, unsigned int nChannels) 394603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 395603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; 396603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 397603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER; 398603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 399603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->channels = nChannels; 400603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi //resetLimiter(limiter); 401603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 402603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 403603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 404603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 405603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* set sampling rate */ 406603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR setLimiterSampleRate(TDLimiterPtr limiter, unsigned int sampleRate) 407603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 408603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int attack, release; 409603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL attackConst, releaseConst, exponent; 410603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi INT e_ans; 411603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 412603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; 413603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 414603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER; 415603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 416603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* update attack and release time in samples */ 417603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attack = (unsigned int)(limiter->attackMs * sampleRate / 1000); 418603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi release = (unsigned int)(limiter->releaseMs * sampleRate / 1000); 419603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 420603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ 421603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi exponent = invFixp(attack+1); 422603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); 423603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attackConst = scaleValue(attackConst, e_ans); 424603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 425603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ 426603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi exponent = invFixp(release + 1); 427603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); 428603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi releaseConst = scaleValue(releaseConst, e_ans); 429603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 430603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attack = attack; 431603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attackConst = attackConst; 432603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->releaseConst = releaseConst; 433603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->sampleRate = sampleRate; 434603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 435603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* reset */ 436603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi //resetLimiter(limiter); 437603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 438603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 439603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 440603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 441603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* set attack time */ 442603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR setLimiterAttack(TDLimiterPtr limiter, unsigned int attackMs) 443603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 444603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int attack; 445603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL attackConst, exponent; 446603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi INT e_ans; 447603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 448603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; 449603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 450603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER; 451603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 452603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* calculate attack time in samples */ 453603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attack = (unsigned int)(attackMs * limiter->sampleRate / 1000); 454603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 455603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ 456603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi exponent = invFixp(attack+1); 457603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); 458603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi attackConst = scaleValue(attackConst, e_ans); 459603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 460603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attack = attack; 461603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attackConst = attackConst; 462603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->attackMs = attackMs; 463603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 464603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 465603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 466603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 467603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* set release time */ 468603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR setLimiterRelease(TDLimiterPtr limiter, unsigned int releaseMs) 469603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 470603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi unsigned int release; 471603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi FIXP_DBL releaseConst, exponent; 472603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi INT e_ans; 473603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 474603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; 475603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 476603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* calculate release time in samples */ 477603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi release = (unsigned int)(releaseMs * limiter->sampleRate / 1000); 478603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 479603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ 480603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi exponent = invFixp(release + 1); 481603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); 482603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi releaseConst = scaleValue(releaseConst, e_ans); 483603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 484603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->releaseConst = releaseConst; 485603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->releaseMs = releaseMs; 486603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 487603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 488603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 489603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 490603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi/* set limiter threshold */ 491603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel TriviTDLIMITER_ERROR setLimiterThreshold(TDLimiterPtr limiter, INT_PCM threshold) 492603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi{ 493603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; 494603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 495603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi limiter->threshold = (FIXP_PCM)threshold; 496603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi 497603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi return TDLIMIT_OK; 498603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi} 499