1*b9df5ad1SAndroid Build Coastguard Worker /* 2*b9df5ad1SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*b9df5ad1SAndroid Build Coastguard Worker * 4*b9df5ad1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*b9df5ad1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*b9df5ad1SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*b9df5ad1SAndroid Build Coastguard Worker * 8*b9df5ad1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*b9df5ad1SAndroid Build Coastguard Worker * 10*b9df5ad1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*b9df5ad1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*b9df5ad1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*b9df5ad1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*b9df5ad1SAndroid Build Coastguard Worker * limitations under the License. 15*b9df5ad1SAndroid Build Coastguard Worker */ 16*b9df5ad1SAndroid Build Coastguard Worker 17*b9df5ad1SAndroid Build Coastguard Worker #include <math.h> 18*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/limiter.h> 19*b9df5ad1SAndroid Build Coastguard Worker 20*b9df5ad1SAndroid Build Coastguard Worker #undef USE_ATAN_APPROXIMATION 21*b9df5ad1SAndroid Build Coastguard Worker 22*b9df5ad1SAndroid Build Coastguard Worker #ifdef USE_ATAN_APPROXIMATION atan_approximation(float in)23*b9df5ad1SAndroid Build Coastguard Workerstatic inline float atan_approximation(float in) 24*b9df5ad1SAndroid Build Coastguard Worker { 25*b9df5ad1SAndroid Build Coastguard Worker static const float kPi_2 = 1.5625; // pi/2 ~= 2.0 * atan_approximation(1.0) 26*b9df5ad1SAndroid Build Coastguard Worker if (in <= 1.0) { 27*b9df5ad1SAndroid Build Coastguard Worker return in / (1.0 + 0.28 * in * in); 28*b9df5ad1SAndroid Build Coastguard Worker } else { 29*b9df5ad1SAndroid Build Coastguard Worker const float in_inverse = 1.0 / in; 30*b9df5ad1SAndroid Build Coastguard Worker return kPi_2 - in_inverse / (1.0 + 0.28 * in_inverse * in_inverse); 31*b9df5ad1SAndroid Build Coastguard Worker } 32*b9df5ad1SAndroid Build Coastguard Worker } 33*b9df5ad1SAndroid Build Coastguard Worker #endif 34*b9df5ad1SAndroid Build Coastguard Worker limiter(float in)35*b9df5ad1SAndroid Build Coastguard Workerfloat limiter(float in) 36*b9df5ad1SAndroid Build Coastguard Worker { 37*b9df5ad1SAndroid Build Coastguard Worker static const float crossover = M_SQRT1_2; 38*b9df5ad1SAndroid Build Coastguard Worker float in_abs = fabsf(in); 39*b9df5ad1SAndroid Build Coastguard Worker if (in_abs <= crossover) { 40*b9df5ad1SAndroid Build Coastguard Worker return in; 41*b9df5ad1SAndroid Build Coastguard Worker } 42*b9df5ad1SAndroid Build Coastguard Worker float out; 43*b9df5ad1SAndroid Build Coastguard Worker #ifdef USE_ATAN_APPROXIMATION 44*b9df5ad1SAndroid Build Coastguard Worker // atan approximation 45*b9df5ad1SAndroid Build Coastguard Worker static const float factor = 4.3125; 46*b9df5ad1SAndroid Build Coastguard Worker static const float ratio = 1.0 / factor; 47*b9df5ad1SAndroid Build Coastguard Worker out = crossover + atan_approximation((in_abs - crossover)*factor)*ratio; 48*b9df5ad1SAndroid Build Coastguard Worker if (out > 1.0) { 49*b9df5ad1SAndroid Build Coastguard Worker out = 1.0; 50*b9df5ad1SAndroid Build Coastguard Worker } 51*b9df5ad1SAndroid Build Coastguard Worker #else 52*b9df5ad1SAndroid Build Coastguard Worker // polynomial spline 53*b9df5ad1SAndroid Build Coastguard Worker static const float A = 0.3431457505; 54*b9df5ad1SAndroid Build Coastguard Worker static const float B = -1.798989873; 55*b9df5ad1SAndroid Build Coastguard Worker static const float C = 3.029437252; 56*b9df5ad1SAndroid Build Coastguard Worker static const float D = -0.6568542495; 57*b9df5ad1SAndroid Build Coastguard Worker // Cubic solution Ax^3 + Bx^2 + Cx + D 58*b9df5ad1SAndroid Build Coastguard Worker if (in_abs < M_SQRT2) { 59*b9df5ad1SAndroid Build Coastguard Worker // TODO Use Estrin's method P3 60*b9df5ad1SAndroid Build Coastguard Worker out = ((A*in_abs + B)*in_abs + C)*in_abs + D; 61*b9df5ad1SAndroid Build Coastguard Worker } else { 62*b9df5ad1SAndroid Build Coastguard Worker out = 1.0; 63*b9df5ad1SAndroid Build Coastguard Worker } 64*b9df5ad1SAndroid Build Coastguard Worker #endif 65*b9df5ad1SAndroid Build Coastguard Worker if (in < 0) { 66*b9df5ad1SAndroid Build Coastguard Worker out = -out; 67*b9df5ad1SAndroid Build Coastguard Worker } 68*b9df5ad1SAndroid Build Coastguard Worker return out; 69*b9df5ad1SAndroid Build Coastguard Worker } 70