Home | History | Annotate | Download | only in testlibs
      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 
     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 
     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 
     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 
     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 
     77 void AudioEqualizer::free() {
     78     ALOGV("AudioEqualizer::free()");
     79     if (mpMem != NULL) {
     80         ::free(mpMem);
     81     }
     82 }
     83 
     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 
    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 
    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 
    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 
    141 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 
    152 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 
    163 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 
    172 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 
    186 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 
    195 int AudioEqualizer::getNumPresets() const {
    196     return mNumPresets;
    197 }
    198 
    199 int AudioEqualizer::getPreset() const {
    200     return mCurPreset;
    201 }
    202 
    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 
    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 
    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 
    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 
    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 
    254 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 
    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