1135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent/* //device/include/server/AudioFlinger/AudioPeakingFilter.cpp 2135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 3135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** Copyright 2007, The Android Open Source Project 4135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 5135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** Licensed under the Apache License, Version 2.0 (the "License"); 6135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** you may not use this file except in compliance with the License. 7135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** You may obtain a copy of the License at 8135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 9135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** http://www.apache.org/licenses/LICENSE-2.0 10135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 11135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** Unless required by applicable law or agreed to in writing, software 12135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** distributed under the License is distributed on an "AS IS" BASIS, 13135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** See the License for the specific language governing permissions and 15135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** limitations under the License. 16135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent */ 17135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 18135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include "AudioPeakingFilter.h" 19135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include "AudioCommon.h" 20135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include "EffectsMath.h" 21135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 22135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include <new> 23135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include <assert.h> 24f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten#include <cutils/compiler.h> 25135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 26135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentnamespace android { 27135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// Format of the coefficient table: 28135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// kCoefTable[freq][gain][bw][coef] 29135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// freq - peak frequency, in octaves below Nyquist,from -9 to -1. 30135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel. 31135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// bw - bandwidth, starting at 1 cent, jumps of 1024, to 3073 cents. 32135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// coef - 0: b0 33135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// 1: b1 34135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// 2: b2 35135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// 3: -a1 36135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// 4: -a2 37135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentstatic const size_t kInDims[3] = {9, 15, 4}; 38135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentstatic const audio_coef_t kCoefTable[9*15*4*5] = { 39135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include "AudioPeakingFilterCoef.inl" 40135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent}; 41135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 42135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric LaurentAudioCoefInterpolator AudioPeakingFilter::mCoefInterp(3, kInDims, 5, (const audio_coef_t*) kCoefTable); 43135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 44135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric LaurentAudioPeakingFilter::AudioPeakingFilter(int nChannels, int sampleRate) 45135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent : mBiquad(nChannels, sampleRate) { 46135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent configure(nChannels, sampleRate); 47135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent reset(); 48135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 49135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 50135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::configure(int nChannels, int sampleRate) { 51135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNiquistFreq = sampleRate * 500; 52135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mFrequencyFactor = ((1ull) << 42) / mNiquistFreq; 53135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBiquad.configure(nChannels, sampleRate); 54135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setFrequency(mNominalFrequency); 55135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent commit(true); 56135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 57135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 58135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::reset() { 59135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setGain(0); 60135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setFrequency(0); 61135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setBandwidth(2400); 62135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent commit(true); 63135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 64135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 65135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::setFrequency(uint32_t millihertz) { 66135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNominalFrequency = millihertz; 67f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(millihertz > mNiquistFreq / 2)) { 68135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent millihertz = mNiquistFreq / 2; 69135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 70135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t normFreq = static_cast<uint32_t>( 71135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10); 72f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_LIKELY(normFreq > (1 << 23))) { 73135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mFrequency = (Effects_log2(normFreq) - ((32-9) << 15)) << (FREQ_PRECISION_BITS - 15); 74135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 75135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mFrequency = 0; 76135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 77135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 78135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 79135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::setGain(int32_t millibel) { 80135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mGain = millibel + 9600; 81135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 82135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 83135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::setBandwidth(uint32_t cents) { 84135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBandwidth = cents - 1; 85135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 86135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 87135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::commit(bool immediate) { 88135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_t coefs[5]; 89135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int intCoord[3] = { 90135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mFrequency >> FREQ_PRECISION_BITS, 91135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mGain >> GAIN_PRECISION_BITS, 92135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBandwidth >> BANDWIDTH_PRECISION_BITS 93135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent }; 94135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t fracCoord[3] = { 95135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mFrequency << (32 - FREQ_PRECISION_BITS), 96135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS), 97135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBandwidth << (32 - BANDWIDTH_PRECISION_BITS) 98135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent }; 99135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefInterp.getCoef(intCoord, fracCoord, coefs); 100135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBiquad.setCoefs(coefs, immediate); 101135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 102135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 103135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioPeakingFilter::getBandRange(uint32_t & low, uint32_t & high) const { 104135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Half bandwidth, in octaves, 15-bit precision 105135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int32_t halfBW = (((mBandwidth + 1) / 2) << 15) / 1200; 106135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 107135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent low = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16); 108f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(halfBW >= (16 << 15))) { 109135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent high = mNiquistFreq; 110135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 111135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent high = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16); 112f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(high > mNiquistFreq)) { 113135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent high = mNiquistFreq; 114135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 115135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 116135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 117135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 118135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 119135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 120