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 29namespace android { 30 31size_t AudioEqualizer::GetInstanceSize(int nBands) { 32 assert(nBands >= 2); 33 return sizeof(AudioEqualizer) + 34 sizeof(AudioShelvingFilter) * 2 + 35 sizeof(AudioPeakingFilter) * (nBands - 2); 36} 37 38AudioEqualizer * 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 58void 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 68void 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 77void AudioEqualizer::free() { 78 ALOGV("AudioEqualizer::free()"); 79 if (mpMem != NULL) { 80 ::free(mpMem); 81 } 82} 83 84void 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 105void 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 118void 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 132void 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 141int32_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 152uint32_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 163uint32_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 172void 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 186const 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 195int AudioEqualizer::getNumPresets() const { 196 return mNumPresets; 197} 198 199int AudioEqualizer::getPreset() const { 200 return mCurPreset; 201} 202 203void 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 216void 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 225void 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 236void 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 245void 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 254int 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 287AudioEqualizer::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