1 /*
2 * Copyright 2009, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "AudioEqualizer"
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <new>
22 #include <utils/Log.h>
23
24 #include "AudioEqualizer.h"
25 #include "AudioPeakingFilter.h"
26 #include "AudioShelvingFilter.h"
27 #include "EffectsMath.h"
28
29 namespace android {
30
GetInstanceSize(int nBands)31 size_t AudioEqualizer::GetInstanceSize(int nBands) {
32 assert(nBands >= 2);
33 return sizeof(AudioEqualizer) +
34 sizeof(AudioShelvingFilter) * 2 +
35 sizeof(AudioPeakingFilter) * (nBands - 2);
36 }
37
CreateInstance(void * pMem,int nBands,int nChannels,int sampleRate,const PresetConfig * presets,int nPresets)38 AudioEqualizer * AudioEqualizer::CreateInstance(void * pMem, int nBands,
39 int nChannels, int sampleRate,
40 const PresetConfig * presets,
41 int nPresets) {
42 ALOGV("AudioEqualizer::CreateInstance(pMem=%p, nBands=%d, nChannels=%d, "
43 "sampleRate=%d, nPresets=%d)",
44 pMem, nBands, nChannels, sampleRate, nPresets);
45 assert(nBands >= 2);
46 bool ownMem = false;
47 if (pMem == NULL) {
48 pMem = malloc(GetInstanceSize(nBands));
49 if (pMem == NULL) {
50 return NULL;
51 }
52 ownMem = true;
53 }
54 return new (pMem) AudioEqualizer(pMem, nBands, nChannels, sampleRate,
55 ownMem, presets, nPresets);
56 }
57
configure(int nChannels,int sampleRate)58 void AudioEqualizer::configure(int nChannels, int sampleRate) {
59 ALOGV("AudioEqualizer::configure(nChannels=%d, sampleRate=%d)", nChannels,
60 sampleRate);
61 mpLowShelf->configure(nChannels, sampleRate);
62 for (int i = 0; i < mNumPeaking; ++i) {
63 mpPeakingFilters[i].configure(nChannels, sampleRate);
64 }
65 mpHighShelf->configure(nChannels, sampleRate);
66 }
67
clear()68 void AudioEqualizer::clear() {
69 ALOGV("AudioEqualizer::clear()");
70 mpLowShelf->clear();
71 for (int i = 0; i < mNumPeaking; ++i) {
72 mpPeakingFilters[i].clear();
73 }
74 mpHighShelf->clear();
75 }
76
free()77 void AudioEqualizer::free() {
78 ALOGV("AudioEqualizer::free()");
79 if (mpMem != NULL) {
80 ::free(mpMem);
81 }
82 }
83
reset()84 void AudioEqualizer::reset() {
85 ALOGV("AudioEqualizer::reset()");
86 const int32_t bottom = Effects_log2(kMinFreq);
87 const int32_t top = Effects_log2(mSampleRate * 500);
88 const int32_t jump = (top - bottom) / (mNumPeaking + 2);
89 int32_t centerFreq = bottom + jump/2;
90
91 mpLowShelf->reset();
92 mpLowShelf->setFrequency(Effects_exp2(centerFreq));
93 centerFreq += jump;
94 for (int i = 0; i < mNumPeaking; ++i) {
95 mpPeakingFilters[i].reset();
96 mpPeakingFilters[i].setFrequency(Effects_exp2(centerFreq));
97 centerFreq += jump;
98 }
99 mpHighShelf->reset();
100 mpHighShelf->setFrequency(Effects_exp2(centerFreq));
101 commit(true);
102 mCurPreset = PRESET_CUSTOM;
103 }
104
setGain(int band,int32_t millibel)105 void AudioEqualizer::setGain(int band, int32_t millibel) {
106 ALOGV("AudioEqualizer::setGain(band=%d, millibel=%d)", band, millibel);
107 assert(band >= 0 && band < mNumPeaking + 2);
108 if (band == 0) {
109 mpLowShelf->setGain(millibel);
110 } else if (band == mNumPeaking + 1) {
111 mpHighShelf->setGain(millibel);
112 } else {
113 mpPeakingFilters[band - 1].setGain(millibel);
114 }
115 mCurPreset = PRESET_CUSTOM;
116 }
117
setFrequency(int band,uint32_t millihertz)118 void AudioEqualizer::setFrequency(int band, uint32_t millihertz) {
119 ALOGV("AudioEqualizer::setFrequency(band=%d, millihertz=%d)", band,
120 millihertz);
121 assert(band >= 0 && band < mNumPeaking + 2);
122 if (band == 0) {
123 mpLowShelf->setFrequency(millihertz);
124 } else if (band == mNumPeaking + 1) {
125 mpHighShelf->setFrequency(millihertz);
126 } else {
127 mpPeakingFilters[band - 1].setFrequency(millihertz);
128 }
129 mCurPreset = PRESET_CUSTOM;
130 }
131
setBandwidth(int band,uint32_t cents)132 void AudioEqualizer::setBandwidth(int band, uint32_t cents) {
133 ALOGV("AudioEqualizer::setBandwidth(band=%d, cents=%d)", band, cents);
134 assert(band >= 0 && band < mNumPeaking + 2);
135 if (band > 0 && band < mNumPeaking + 1) {
136 mpPeakingFilters[band - 1].setBandwidth(cents);
137 mCurPreset = PRESET_CUSTOM;
138 }
139 }
140
getGain(int band) const141 int32_t AudioEqualizer::getGain(int band) const {
142 assert(band >= 0 && band < mNumPeaking + 2);
143 if (band == 0) {
144 return mpLowShelf->getGain();
145 } else if (band == mNumPeaking + 1) {
146 return mpHighShelf->getGain();
147 } else {
148 return mpPeakingFilters[band - 1].getGain();
149 }
150 }
151
getFrequency(int band) const152 uint32_t AudioEqualizer::getFrequency(int band) const {
153 assert(band >= 0 && band < mNumPeaking + 2);
154 if (band == 0) {
155 return mpLowShelf->getFrequency();
156 } else if (band == mNumPeaking + 1) {
157 return mpHighShelf->getFrequency();
158 } else {
159 return mpPeakingFilters[band - 1].getFrequency();
160 }
161 }
162
getBandwidth(int band) const163 uint32_t AudioEqualizer::getBandwidth(int band) const {
164 assert(band >= 0 && band < mNumPeaking + 2);
165 if (band == 0 || band == mNumPeaking + 1) {
166 return 0;
167 } else {
168 return mpPeakingFilters[band - 1].getBandwidth();
169 }
170 }
171
getBandRange(int band,uint32_t & low,uint32_t & high) const172 void AudioEqualizer::getBandRange(int band, uint32_t & low,
173 uint32_t & high) const {
174 assert(band >= 0 && band < mNumPeaking + 2);
175 if (band == 0) {
176 low = 0;
177 high = mpLowShelf->getFrequency();
178 } else if (band == mNumPeaking + 1) {
179 low = mpHighShelf->getFrequency();
180 high = mSampleRate * 500;
181 } else {
182 mpPeakingFilters[band - 1].getBandRange(low, high);
183 }
184 }
185
getPresetName(int preset) const186 const char * AudioEqualizer::getPresetName(int preset) const {
187 assert(preset < mNumPresets && preset >= PRESET_CUSTOM);
188 if (preset == PRESET_CUSTOM) {
189 return "Custom";
190 } else {
191 return mpPresets[preset].name;
192 }
193 }
194
getNumPresets() const195 int AudioEqualizer::getNumPresets() const {
196 return mNumPresets;
197 }
198
getPreset() const199 int AudioEqualizer::getPreset() const {
200 return mCurPreset;
201 }
202
setPreset(int preset)203 void AudioEqualizer::setPreset(int preset) {
204 ALOGV("AudioEqualizer::setPreset(preset=%d)", preset);
205 assert(preset < mNumPresets && preset >= 0);
206 const PresetConfig &presetCfg = mpPresets[preset];
207 for (int band = 0; band < (mNumPeaking + 2); ++band) {
208 const BandConfig & bandCfg = presetCfg.bandConfigs[band];
209 setGain(band, bandCfg.gain);
210 setFrequency(band, bandCfg.freq);
211 setBandwidth(band, bandCfg.bandwidth);
212 }
213 mCurPreset = preset;
214 }
215
commit(bool immediate)216 void AudioEqualizer::commit(bool immediate) {
217 ALOGV("AudioEqualizer::commit(immediate=%d)", immediate);
218 mpLowShelf->commit(immediate);
219 for (int i = 0; i < mNumPeaking; ++i) {
220 mpPeakingFilters[i].commit(immediate);
221 }
222 mpHighShelf->commit(immediate);
223 }
224
process(const audio_sample_t * pIn,audio_sample_t * pOut,int frameCount)225 void AudioEqualizer::process(const audio_sample_t * pIn,
226 audio_sample_t * pOut,
227 int frameCount) {
228 // ALOGV("AudioEqualizer::process(frameCount=%d)", frameCount);
229 mpLowShelf->process(pIn, pOut, frameCount);
230 for (int i = 0; i < mNumPeaking; ++i) {
231 mpPeakingFilters[i].process(pIn, pOut, frameCount);
232 }
233 mpHighShelf->process(pIn, pOut, frameCount);
234 }
235
enable(bool immediate)236 void AudioEqualizer::enable(bool immediate) {
237 ALOGV("AudioEqualizer::enable(immediate=%d)", immediate);
238 mpLowShelf->enable(immediate);
239 for (int i = 0; i < mNumPeaking; ++i) {
240 mpPeakingFilters[i].enable(immediate);
241 }
242 mpHighShelf->enable(immediate);
243 }
244
disable(bool immediate)245 void AudioEqualizer::disable(bool immediate) {
246 ALOGV("AudioEqualizer::disable(immediate=%d)", immediate);
247 mpLowShelf->disable(immediate);
248 for (int i = 0; i < mNumPeaking; ++i) {
249 mpPeakingFilters[i].disable(immediate);
250 }
251 mpHighShelf->disable(immediate);
252 }
253
getMostRelevantBand(uint32_t targetFreq) const254 int AudioEqualizer::getMostRelevantBand(uint32_t targetFreq) const {
255 // First, find the two bands that the target frequency is between.
256 uint32_t low = mpLowShelf->getFrequency();
257 if (targetFreq <= low) {
258 return 0;
259 }
260 uint32_t high = mpHighShelf->getFrequency();
261 if (targetFreq >= high) {
262 return mNumPeaking + 1;
263 }
264 int band = mNumPeaking;
265 for (int i = 0; i < mNumPeaking; ++i) {
266 uint32_t freq = mpPeakingFilters[i].getFrequency();
267 if (freq >= targetFreq) {
268 high = freq;
269 band = i;
270 break;
271 }
272 low = freq;
273 }
274 // Now, low is right below the target and high is right above. See which one
275 // is closer on a log scale.
276 low = Effects_log2(low);
277 high = Effects_log2(high);
278 targetFreq = Effects_log2(targetFreq);
279 if (high - targetFreq < targetFreq - low) {
280 return band + 1;
281 } else {
282 return band;
283 }
284 }
285
286
AudioEqualizer(void * pMem,int nBands,int nChannels,int sampleRate,bool ownMem,const PresetConfig * presets,int nPresets)287 AudioEqualizer::AudioEqualizer(void * pMem, int nBands, int nChannels,
288 int sampleRate, bool ownMem,
289 const PresetConfig * presets, int nPresets)
290 : mSampleRate(sampleRate)
291 , mpPresets(presets)
292 , mNumPresets(nPresets) {
293 assert(pMem != NULL);
294 assert(nPresets == 0 || nPresets > 0 && presets != NULL);
295 mpMem = ownMem ? pMem : NULL;
296
297 pMem = (char *) pMem + sizeof(AudioEqualizer);
298 mpLowShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kLowShelf,
299 nChannels, sampleRate);
300 pMem = (char *) pMem + sizeof(AudioShelvingFilter);
301 mpHighShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kHighShelf,
302 nChannels, sampleRate);
303 pMem = (char *) pMem + sizeof(AudioShelvingFilter);
304 mNumPeaking = nBands - 2;
305 if (mNumPeaking > 0) {
306 mpPeakingFilters = reinterpret_cast<AudioPeakingFilter *>(pMem);
307 for (int i = 0; i < mNumPeaking; ++i) {
308 new (&mpPeakingFilters[i]) AudioPeakingFilter(nChannels,
309 sampleRate);
310 }
311 }
312 reset();
313 }
314
315 }
316