blob: 99323acd6b498b2f0f0bf034c5825fe628b2054b [file] [log] [blame]
Eric Laurent5fe37c62010-05-21 06:05:13 -07001/* //device/include/server/AudioFlinger/AudioPeakingFilter.cpp
2 **
3 ** Copyright 2007, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18#include "AudioPeakingFilter.h"
19#include "AudioCommon.h"
20#include "EffectsMath.h"
21
22#include <new>
23#include <assert.h>
Glenn Kastene80a4cc2011-12-15 09:51:17 -080024#include <cutils/compiler.h>
Eric Laurent5fe37c62010-05-21 06:05:13 -070025
26namespace android {
27// Format of the coefficient table:
28// kCoefTable[freq][gain][bw][coef]
29// freq - peak frequency, in octaves below Nyquist,from -9 to -1.
30// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
31// bw - bandwidth, starting at 1 cent, jumps of 1024, to 3073 cents.
32// coef - 0: b0
33// 1: b1
34// 2: b2
35// 3: -a1
36// 4: -a2
37static const size_t kInDims[3] = {9, 15, 4};
38static const audio_coef_t kCoefTable[9*15*4*5] = {
39#include "AudioPeakingFilterCoef.inl"
40};
41
42AudioCoefInterpolator AudioPeakingFilter::mCoefInterp(3, kInDims, 5, (const audio_coef_t*) kCoefTable);
43
44AudioPeakingFilter::AudioPeakingFilter(int nChannels, int sampleRate)
45 : mBiquad(nChannels, sampleRate) {
46 configure(nChannels, sampleRate);
47 reset();
48}
49
50void AudioPeakingFilter::configure(int nChannels, int sampleRate) {
51 mNiquistFreq = sampleRate * 500;
52 mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
53 mBiquad.configure(nChannels, sampleRate);
54 setFrequency(mNominalFrequency);
55 commit(true);
56}
57
58void AudioPeakingFilter::reset() {
59 setGain(0);
60 setFrequency(0);
61 setBandwidth(2400);
62 commit(true);
63}
64
65void AudioPeakingFilter::setFrequency(uint32_t millihertz) {
66 mNominalFrequency = millihertz;
Glenn Kastene80a4cc2011-12-15 09:51:17 -080067 if (CC_UNLIKELY(millihertz > mNiquistFreq / 2)) {
Eric Laurent5fe37c62010-05-21 06:05:13 -070068 millihertz = mNiquistFreq / 2;
69 }
70 uint32_t normFreq = static_cast<uint32_t>(
71 (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
Glenn Kastene80a4cc2011-12-15 09:51:17 -080072 if (CC_LIKELY(normFreq > (1 << 23))) {
Eric Laurent5fe37c62010-05-21 06:05:13 -070073 mFrequency = (Effects_log2(normFreq) - ((32-9) << 15)) << (FREQ_PRECISION_BITS - 15);
74 } else {
75 mFrequency = 0;
76 }
77}
78
79void AudioPeakingFilter::setGain(int32_t millibel) {
80 mGain = millibel + 9600;
81}
82
83void AudioPeakingFilter::setBandwidth(uint32_t cents) {
84 mBandwidth = cents - 1;
85}
86
87void AudioPeakingFilter::commit(bool immediate) {
88 audio_coef_t coefs[5];
89 int intCoord[3] = {
90 mFrequency >> FREQ_PRECISION_BITS,
91 mGain >> GAIN_PRECISION_BITS,
92 mBandwidth >> BANDWIDTH_PRECISION_BITS
93 };
94 uint32_t fracCoord[3] = {
95 mFrequency << (32 - FREQ_PRECISION_BITS),
96 static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS),
97 mBandwidth << (32 - BANDWIDTH_PRECISION_BITS)
98 };
99 mCoefInterp.getCoef(intCoord, fracCoord, coefs);
100 mBiquad.setCoefs(coefs, immediate);
101}
102
103void AudioPeakingFilter::getBandRange(uint32_t & low, uint32_t & high) const {
104 // Half bandwidth, in octaves, 15-bit precision
105 int32_t halfBW = (((mBandwidth + 1) / 2) << 15) / 1200;
106
107 low = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16);
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800108 if (CC_UNLIKELY(halfBW >= (16 << 15))) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700109 high = mNiquistFreq;
110 } else {
111 high = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16);
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800112 if (CC_UNLIKELY(high > mNiquistFreq)) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700113 high = mNiquistFreq;
114 }
115 }
116}
117
118}
119