15fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.cpp 25fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 35fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** Copyright 2009, The Android Open Source Project 45fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 55fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** Licensed under the Apache License, Version 2.0 (the "License"); 65fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** you may not use this file except in compliance with the License. 75fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** You may obtain a copy of the License at 85fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 95fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** http://www.apache.org/licenses/LICENSE-2.0 105fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 115fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** Unless required by applicable law or agreed to in writing, software 125fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** distributed under the License is distributed on an "AS IS" BASIS, 135fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** See the License for the specific language governing permissions and 155fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** limitations under the License. 165fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent*/ 175fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 185fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include "AudioShelvingFilter.h" 195fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include "AudioCommon.h" 205fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include "EffectsMath.h" 215fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 225fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include <new> 235fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include <assert.h> 245fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 255fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) 265fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) 275fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 285fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentnamespace android { 295fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// Format of the coefficient tables: 305fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// kCoefTable[freq][gain][coef] 315fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// freq - cutoff frequency, in octaves below Nyquist,from -10 to -6 in low 325fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// shelf, -2 to 0 in high shelf. 335fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel. 345fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// coef - 0: b0 355fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// 1: b1 365fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// 2: b2 375fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// 3: -a1 385fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// 4: -a2 395fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentstatic const size_t kHiInDims[2] = {3, 15}; 405fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentstatic const audio_coef_t kHiCoefTable[3*15*5] = { 415fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include "AudioHighShelfFilterCoef.inl" 425fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent}; 435fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentstatic const size_t kLoInDims[2] = {5, 15}; 445fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentstatic const audio_coef_t kLoCoefTable[5*15*5] = { 455fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include "AudioLowShelfFilterCoef.inl" 465fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent}; 475fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 485fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric LaurentAudioCoefInterpolator AudioShelvingFilter::mHiCoefInterp(2, kHiInDims, 5, (const audio_coef_t*) kHiCoefTable); 495fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric LaurentAudioCoefInterpolator AudioShelvingFilter::mLoCoefInterp(2, kLoInDims, 5, (const audio_coef_t*) kLoCoefTable); 505fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 515fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric LaurentAudioShelvingFilter::AudioShelvingFilter(ShelfType type, int nChannels, 525fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int sampleRate) 5353334cdb81bab4a4dfd0a41d2ef50709015a36c8Eric Laurent : mType(type), 5453334cdb81bab4a4dfd0a41d2ef50709015a36c8Eric Laurent mBiquad(nChannels, sampleRate) { 555fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent configure(nChannels, sampleRate); 565fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 575fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 585fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentvoid AudioShelvingFilter::configure(int nChannels, int sampleRate) { 595fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mNiquistFreq = sampleRate * 500; 605fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mFrequencyFactor = ((1ull) << 42) / mNiquistFreq; 615fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mBiquad.configure(nChannels, sampleRate); 625fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent setFrequency(mNominalFrequency); 635fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent commit(true); 645fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 655fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 665fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentvoid AudioShelvingFilter::reset() { 675fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent setGain(0); 685fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent setFrequency(mType == kLowShelf ? 0 : mNiquistFreq); 695fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent commit(true); 705fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 715fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 725fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentvoid AudioShelvingFilter::setFrequency(uint32_t millihertz) { 735fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mNominalFrequency = millihertz; 745fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent if (UNLIKELY(millihertz > mNiquistFreq / 2)) { 755fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent millihertz = mNiquistFreq / 2; 765fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent } 775fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent uint32_t normFreq = static_cast<uint32_t>( 785fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10); 795fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent uint32_t log2minFreq = (mType == kLowShelf ? (32-10) : (32-2)); 805fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent if (LIKELY(normFreq > (1U << log2minFreq))) { 815fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mFrequency = (Effects_log2(normFreq) - (log2minFreq << 15)) << (FREQ_PRECISION_BITS - 15); 825fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent } else { 835fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mFrequency = 0; 845fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent } 855fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 865fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 875fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentvoid AudioShelvingFilter::setGain(int32_t millibel) { 885fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mGain = millibel + 9600; 895fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 905fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 915fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentvoid AudioShelvingFilter::commit(bool immediate) { 925fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_coef_t coefs[5]; 935fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int intCoord[2] = { 945fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mFrequency >> FREQ_PRECISION_BITS, 955fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mGain >> GAIN_PRECISION_BITS 965fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent }; 975fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent uint32_t fracCoord[2] = { 985fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mFrequency << (32 - FREQ_PRECISION_BITS), 995fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS) 1005fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent }; 1015fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent if (mType == kHighShelf) { 1025fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mHiCoefInterp.getCoef(intCoord, fracCoord, coefs); 1035fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent } else { 1045fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mLoCoefInterp.getCoef(intCoord, fracCoord, coefs); 1055fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent } 1065fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent mBiquad.setCoefs(coefs, immediate); 1075fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 1085fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1095fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 110