EffectEqualizer.cpp revision 5ff1dd576bb93c45b44088a51544a18fc43ebf58
15541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown/*
25541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Copyright (C) 2009 The Android Open Source Project
35541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
45541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
55541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * you may not use this file except in compliance with the License.
65541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * You may obtain a copy of the License at
75541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
85541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
95541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Unless required by applicable law or agreed to in writing, software
115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * See the License for the specific language governing permissions and
145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * limitations under the License.
155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown */
165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#define LOG_TAG "Equalizer"
185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#define LOG_NDEBUG 0
215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <cutils/log.h>
225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <assert.h>
238335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <stdlib.h>
245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <string.h>
255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <new>
265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include "AudioEqualizer.h"
275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include "AudioBiquadFilter.h"
285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include "AudioFormatAdapter.h"
295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <audio_effects/effect_equalizer.h>
305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// effect_handle_t interface implementation for equalizer effect
335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownextern "C" const struct effect_interface_s gEqualizerInterface;
342352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
352352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownenum equalizer_state_e {
365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    EQUALIZER_STATE_UNINITIALIZED,
375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    EQUALIZER_STATE_INITIALIZED,
385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    EQUALIZER_STATE_ACTIVE,
395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown};
405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace android {
425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace {
435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownconst effect_descriptor_t gEqualizerDescriptor = {
465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        EFFECT_CONTROL_API_VERSION,
495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        0, // TODO
515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        1,
525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        "Graphic Equalizer",
535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        "The Android Open Source Project",
545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown};
552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
562352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownconst int kNumBands = 5;
582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownconst uint32_t gFreqs[kNumBands] =      { 50000, 125000, 900000, 3200000, 6300000 };
592352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownconst uint32_t gBandwidths[kNumBands] = { 0,     3600,   3600,   2400,    0       };
602352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
612352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownconst AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
622352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 300,  gFreqs[0], gBandwidths[0] },
632352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 400,  gFreqs[1], gBandwidths[1] },
642352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 0,    gFreqs[2], gBandwidths[2] },
652352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 200,  gFreqs[3], gBandwidths[3] },
662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { -300, gFreqs[4], gBandwidths[4] }
672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown};
682352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
692352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownconst AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
702352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { -600, gFreqs[0], gBandwidths[0] },
712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 200,  gFreqs[1], gBandwidths[1] },
722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 400,  gFreqs[2], gBandwidths[2] },
732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { -400, gFreqs[3], gBandwidths[3] },
742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { -600, gFreqs[4], gBandwidths[4] }
752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown};
762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownconst AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 400,  gFreqs[0], gBandwidths[0] },
792352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { -400, gFreqs[1], gBandwidths[1] },
802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 300,  gFreqs[2], gBandwidths[2] },
812352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { -400, gFreqs[3], gBandwidths[3] },
822352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { 600,  gFreqs[4], gBandwidths[4] }
832352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown};
845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownconst AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { 700,  gFreqs[0], gBandwidths[0] },
875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { 400,  gFreqs[1], gBandwidths[1] },
885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { -400, gFreqs[2], gBandwidths[2] },
895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { 400,  gFreqs[3], gBandwidths[3] },
905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { 200,  gFreqs[4], gBandwidths[4] }
915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown};
925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownconst AudioEqualizer::PresetConfig gEqualizerPresets[] = {
942352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { "Classic", gBandsClassic },
952352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { "Jazz",    gBandsJazz    },
962352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { "Pop",     gBandsPop     },
972352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    { "Rock",    gBandsRock    }
982352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown};
992352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1002352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown/////////////////// END EQ PRESETS /////////////////////////////////////////////
1012352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownstatic const size_t kBufferSize = 32;
1035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1042352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Browntypedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
1052352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1062352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownstruct EqualizerContext {
1072352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    const struct effect_interface_s *itfe;
1082352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    effect_config_t config;
1095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    FormatAdapter adapter;
1105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AudioEqualizer * pEqualizer;
1115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    uint32_t state;
1125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown};
1135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//--- local function prototypes
1155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownint Equalizer_init(EqualizerContext *pContext);
1175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownint Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig);
1185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownint Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
1195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownint Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
1205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
1235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//--- Effect Library Interface Implementation
1245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
1255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownextern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
1275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    *pNumEffects = 1;
1285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return 0;
1295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} /* end EffectQueryNumberEffects */
1305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownextern "C" int EffectQueryEffect(uint32_t index,
1325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                                 effect_descriptor_t *pDescriptor) {
1335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (pDescriptor == NULL) {
1345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return -EINVAL;
1355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (index > 0) {
1375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return -EINVAL;
1385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
1405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return 0;
1415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} /* end EffectQueryNext */
1425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownextern "C" int EffectCreate(effect_uuid_t *uuid,
1445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            int32_t sessionId,
1455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            int32_t ioId,
1465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            effect_handle_t *pHandle) {
1475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    int ret;
1482352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    int i;
1492352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1502352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    ALOGV("EffectLibCreateEffect start");
1512352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1522352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (pHandle == NULL || uuid == NULL) {
1532352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return -EINVAL;
1542352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
1552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
1565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
1575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return -EINVAL;
1585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    EqualizerContext *pContext = new EqualizerContext;
1615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->itfe = &gEqualizerInterface;
1635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->pEqualizer = NULL;
1645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
1655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ret = Equalizer_init(pContext);
1675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (ret < 0) {
1685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        ALOGW("EffectLibCreateEffect() init failed");
1695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        delete pContext;
1705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return ret;
1715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    *pHandle = (effect_handle_t)pContext;
1745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->state = EQUALIZER_STATE_INITIALIZED;
1755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ALOGV("EffectLibCreateEffect %p, size %d",
1775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown         pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
1785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1792352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    return 0;
1805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} /* end EffectCreate */
1825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownextern "C" int EffectRelease(effect_handle_t handle) {
1845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    EqualizerContext * pContext = (EqualizerContext *)handle;
1855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1862352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    ALOGV("EffectLibReleaseEffect %p", handle);
1875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (pContext == NULL) {
1885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return -EINVAL;
1895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
1925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->pEqualizer->free();
1935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    delete pContext;
1945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return 0;
1965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} /* end EffectRelease */
1975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownextern "C" int EffectGetDescriptor(effect_uuid_t       *uuid,
1995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                                   effect_descriptor_t *pDescriptor) {
2005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2012352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (pDescriptor == NULL || uuid == NULL){
2025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        ALOGV("EffectGetDescriptor() called with NULL pointer");
2035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return -EINVAL;
2045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
2075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
2085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return 0;
2095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return  -EINVAL;
2125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} /* end EffectGetDescriptor */
2135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//--- local functions
2175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2192352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown#define CHECK_ARG(cond) {                     \
2205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (!(cond)) {                            \
2215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        ALOGV("Invalid argument: "#cond);      \
2225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return -EINVAL;                       \
2235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }                                         \
2245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
2255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//----------------------------------------------------------------------------
2272352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown// Equalizer_setConfig()
2285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//----------------------------------------------------------------------------
2295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// Purpose: Set input and output audio configuration.
2305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2312352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown// Inputs:
2325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//  pContext:   effect engine context
2335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//  pConfig:    pointer to effect_config_t structure holding input and output
2345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//      configuration parameters
2355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2362352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown// Outputs:
2372352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown//
2382352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown//----------------------------------------------------------------------------
2392352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
2402352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownint Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig)
2415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown{
2425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ALOGV("Equalizer_setConfig start");
2435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG(pContext != NULL);
2455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG(pConfig != NULL);
2462352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
2472352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
2482352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
2495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
2505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG((pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
2515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown              (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
2525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
2535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
2545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_8_24_BIT
2555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown              || pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
2565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    int channelCount;
2585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) {
2595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        channelCount = 1;
2605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } else {
2615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        channelCount = 2;
2625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
2645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
2665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->pEqualizer->configure(channelCount,
2685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                          pConfig->inputCfg.samplingRate);
2695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    pContext->adapter.configure(*pContext->pEqualizer, channelCount,
2715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        pConfig->inputCfg.format,
2725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        pConfig->outputCfg.accessMode);
2732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
2742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    return 0;
2752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}   // end Equalizer_setConfig
2762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
2772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown//----------------------------------------------------------------------------
2782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown// Equalizer_getConfig()
2795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//----------------------------------------------------------------------------
2805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// Purpose: Get input and output audio configuration.
2815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// Inputs:
2835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//  pContext:   effect engine context
2845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//  pConfig:    pointer to effect_config_t structure holding input and output
2855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//      configuration parameters
2865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// Outputs:
2885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//
2895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//----------------------------------------------------------------------------
2905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid Equalizer_getConfig(EqualizerContext *pContext, effect_config_t *pConfig)
2925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown{
2935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    memcpy(pConfig, &pContext->config, sizeof(effect_config_t));
294}   // end Equalizer_getConfig
295
296
297//----------------------------------------------------------------------------
298// Equalizer_init()
299//----------------------------------------------------------------------------
300// Purpose: Initialize engine with default configuration and creates
301//     AudioEqualizer instance.
302//
303// Inputs:
304//  pContext:   effect engine context
305//
306// Outputs:
307//
308//----------------------------------------------------------------------------
309
310int Equalizer_init(EqualizerContext *pContext)
311{
312    int status;
313
314    ALOGV("Equalizer_init start");
315
316    CHECK_ARG(pContext != NULL);
317
318    if (pContext->pEqualizer != NULL) {
319        pContext->pEqualizer->free();
320    }
321
322    pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
323    pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
324    pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
325    pContext->config.inputCfg.samplingRate = 44100;
326    pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
327    pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
328    pContext->config.inputCfg.bufferProvider.cookie = NULL;
329    pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
330    pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
331    pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
332    pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
333    pContext->config.outputCfg.samplingRate = 44100;
334    pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
335    pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
336    pContext->config.outputCfg.bufferProvider.cookie = NULL;
337    pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
338
339    pContext->pEqualizer = AudioEqualizer::CreateInstance(
340        NULL,
341        kNumBands,
342        AudioBiquadFilter::MAX_CHANNELS,
343        44100,
344        gEqualizerPresets,
345        ARRAY_SIZE(gEqualizerPresets));
346
347    for (int i = 0; i < kNumBands; ++i) {
348        pContext->pEqualizer->setFrequency(i, gFreqs[i]);
349        pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
350    }
351
352    pContext->pEqualizer->enable(true);
353
354    Equalizer_setConfig(pContext, &pContext->config);
355
356    return 0;
357}   // end Equalizer_init
358
359
360//----------------------------------------------------------------------------
361// Equalizer_getParameter()
362//----------------------------------------------------------------------------
363// Purpose:
364// Get a Equalizer parameter
365//
366// Inputs:
367//  pEqualizer       - handle to instance data
368//  pParam           - pointer to parameter
369//  pValue           - pointer to variable to hold retrieved value
370//  pValueSize       - pointer to value size: maximum size as input
371//
372// Outputs:
373//  *pValue updated with parameter value
374//  *pValueSize updated with actual value size
375//
376//
377// Side Effects:
378//
379//----------------------------------------------------------------------------
380
381int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
382{
383    int status = 0;
384    int32_t param = *pParam++;
385    int32_t param2;
386    char *name;
387
388    switch (param) {
389    case EQ_PARAM_NUM_BANDS:
390    case EQ_PARAM_CUR_PRESET:
391    case EQ_PARAM_GET_NUM_OF_PRESETS:
392    case EQ_PARAM_BAND_LEVEL:
393    case EQ_PARAM_GET_BAND:
394        if (*pValueSize < sizeof(int16_t)) {
395            return -EINVAL;
396        }
397        *pValueSize = sizeof(int16_t);
398        break;
399
400    case EQ_PARAM_LEVEL_RANGE:
401        if (*pValueSize < 2 * sizeof(int16_t)) {
402            return -EINVAL;
403        }
404        *pValueSize = 2 * sizeof(int16_t);
405        break;
406
407    case EQ_PARAM_BAND_FREQ_RANGE:
408        if (*pValueSize < 2 * sizeof(int32_t)) {
409            return -EINVAL;
410        }
411        *pValueSize = 2 * sizeof(int32_t);
412        break;
413
414    case EQ_PARAM_CENTER_FREQ:
415        if (*pValueSize < sizeof(int32_t)) {
416            return -EINVAL;
417        }
418        *pValueSize = sizeof(int32_t);
419        break;
420
421    case EQ_PARAM_GET_PRESET_NAME:
422        break;
423
424    case EQ_PARAM_PROPERTIES:
425        if (*pValueSize < (2 + kNumBands) * sizeof(uint16_t)) {
426            return -EINVAL;
427        }
428        *pValueSize = (2 + kNumBands) * sizeof(uint16_t);
429        break;
430
431    default:
432        return -EINVAL;
433    }
434
435    switch (param) {
436    case EQ_PARAM_NUM_BANDS:
437        *(uint16_t *)pValue = (uint16_t)kNumBands;
438        ALOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
439        break;
440
441    case EQ_PARAM_LEVEL_RANGE:
442        *(int16_t *)pValue = -9600;
443        *((int16_t *)pValue + 1) = 4800;
444        ALOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
445             *(int32_t *)pValue, *((int32_t *)pValue + 1));
446        break;
447
448    case EQ_PARAM_BAND_LEVEL:
449        param2 = *pParam;
450        if (param2 >= kNumBands) {
451            status = -EINVAL;
452            break;
453        }
454        *(int16_t *)pValue = (int16_t)pEqualizer->getGain(param2);
455        ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
456             param2, *(int32_t *)pValue);
457        break;
458
459    case EQ_PARAM_CENTER_FREQ:
460        param2 = *pParam;
461        if (param2 >= kNumBands) {
462            status = -EINVAL;
463            break;
464        }
465        *(int32_t *)pValue = pEqualizer->getFrequency(param2);
466        ALOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
467             param2, *(int32_t *)pValue);
468        break;
469
470    case EQ_PARAM_BAND_FREQ_RANGE:
471        param2 = *pParam;
472        if (param2 >= kNumBands) {
473            status = -EINVAL;
474            break;
475        }
476        pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
477        ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
478             param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
479        break;
480
481    case EQ_PARAM_GET_BAND:
482        param2 = *pParam;
483        *(uint16_t *)pValue = (uint16_t)pEqualizer->getMostRelevantBand(param2);
484        ALOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
485             param2, *(int32_t *)pValue);
486        break;
487
488    case EQ_PARAM_CUR_PRESET:
489        *(uint16_t *)pValue = (uint16_t)pEqualizer->getPreset();
490        ALOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
491        break;
492
493    case EQ_PARAM_GET_NUM_OF_PRESETS:
494        *(uint16_t *)pValue = (uint16_t)pEqualizer->getNumPresets();
495        ALOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
496        break;
497
498    case EQ_PARAM_GET_PRESET_NAME:
499        param2 = *pParam;
500        if (param2 >= pEqualizer->getNumPresets()) {
501            status = -EINVAL;
502            break;
503        }
504        name = (char *)pValue;
505        strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
506        name[*pValueSize - 1] = 0;
507        *pValueSize = strlen(name) + 1;
508        ALOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
509             param2, gEqualizerPresets[param2].name, *pValueSize);
510        break;
511
512    case EQ_PARAM_PROPERTIES: {
513        int16_t *p = (int16_t *)pValue;
514        ALOGV("Equalizer_getParameter() EQ_PARAM_PROPERTIES");
515        p[0] = (int16_t)pEqualizer->getPreset();
516        p[1] = (int16_t)kNumBands;
517        for (int i = 0; i < kNumBands; i++) {
518            p[2 + i] = (int16_t)pEqualizer->getGain(i);
519        }
520    } break;
521
522    default:
523        ALOGV("Equalizer_getParameter() invalid param %d", param);
524        status = -EINVAL;
525        break;
526    }
527
528    return status;
529} // end Equalizer_getParameter
530
531
532//----------------------------------------------------------------------------
533// Equalizer_setParameter()
534//----------------------------------------------------------------------------
535// Purpose:
536// Set a Equalizer parameter
537//
538// Inputs:
539//  pEqualizer       - handle to instance data
540//  pParam           - pointer to parameter
541//  pValue           - pointer to value
542//
543// Outputs:
544//
545//
546// Side Effects:
547//
548//----------------------------------------------------------------------------
549
550int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
551{
552    int status = 0;
553    int32_t preset;
554    int32_t band;
555    int32_t level;
556    int32_t param = *pParam++;
557
558
559    switch (param) {
560    case EQ_PARAM_CUR_PRESET:
561        preset = (int32_t)(*(uint16_t *)pValue);
562
563        ALOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
564        if (preset < 0 || preset >= pEqualizer->getNumPresets()) {
565            status = -EINVAL;
566            break;
567        }
568        pEqualizer->setPreset(preset);
569        pEqualizer->commit(true);
570        break;
571    case EQ_PARAM_BAND_LEVEL:
572        band =  *pParam;
573        level = (int32_t)(*(int16_t *)pValue);
574        ALOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
575        if (band >= kNumBands) {
576            status = -EINVAL;
577            break;
578        }
579        pEqualizer->setGain(band, level);
580        pEqualizer->commit(true);
581       break;
582    case EQ_PARAM_PROPERTIES: {
583        ALOGV("setParameter() EQ_PARAM_PROPERTIES");
584        int16_t *p = (int16_t *)pValue;
585        if ((int)p[0] >= pEqualizer->getNumPresets()) {
586            status = -EINVAL;
587            break;
588        }
589        if (p[0] >= 0) {
590            pEqualizer->setPreset((int)p[0]);
591        } else {
592            if ((int)p[1] != kNumBands) {
593                status = -EINVAL;
594                break;
595            }
596            for (int i = 0; i < kNumBands; i++) {
597                pEqualizer->setGain(i, (int32_t)p[2 + i]);
598            }
599        }
600        pEqualizer->commit(true);
601    } break;
602    default:
603        ALOGV("setParameter() invalid param %d", param);
604        status = -EINVAL;
605        break;
606    }
607
608    return status;
609} // end Equalizer_setParameter
610
611} // namespace
612} // namespace
613
614
615//
616//--- Effect Control Interface Implementation
617//
618
619extern "C" int Equalizer_process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
620{
621    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
622
623    if (pContext == NULL) {
624        return -EINVAL;
625    }
626    if (inBuffer == NULL || inBuffer->raw == NULL ||
627        outBuffer == NULL || outBuffer->raw == NULL ||
628        inBuffer->frameCount != outBuffer->frameCount) {
629        return -EINVAL;
630    }
631
632    if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
633        return -EINVAL;
634    }
635    if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
636        return -ENODATA;
637    }
638
639    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
640
641    return 0;
642}   // end Equalizer_process
643
644extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
645        void *pCmdData, uint32_t *replySize, void *pReplyData) {
646
647    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
648    int retsize;
649
650    if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
651        return -EINVAL;
652    }
653
654    android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
655
656    ALOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
657
658    switch (cmdCode) {
659    case EFFECT_CMD_INIT:
660        if (pReplyData == NULL || *replySize != sizeof(int)) {
661            return -EINVAL;
662        }
663        *(int *) pReplyData = Equalizer_init(pContext);
664        break;
665    case EFFECT_CMD_SET_CONFIG:
666        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
667                || pReplyData == NULL || *replySize != sizeof(int)) {
668            return -EINVAL;
669        }
670        *(int *) pReplyData = Equalizer_setConfig(pContext,
671                (effect_config_t *) pCmdData);
672        break;
673    case EFFECT_CMD_GET_CONFIG:
674        if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
675            return -EINVAL;
676        }
677        Equalizer_getConfig(pContext, (effect_config_t *) pCmdData);
678        break;
679    case EFFECT_CMD_RESET:
680        Equalizer_setConfig(pContext, &pContext->config);
681        break;
682    case EFFECT_CMD_GET_PARAM: {
683        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
684            pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
685            return -EINVAL;
686        }
687        effect_param_t *p = (effect_param_t *)pCmdData;
688        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
689        p = (effect_param_t *)pReplyData;
690        int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
691        p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
692                p->data + voffset);
693        *replySize = sizeof(effect_param_t) + voffset + p->vsize;
694        ALOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
695                *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
696                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
697                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
698
699        } break;
700    case EFFECT_CMD_SET_PARAM: {
701        ALOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
702             cmdSize, pCmdData, *replySize, pReplyData);
703        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
704            pReplyData == NULL || *replySize != sizeof(int32_t)) {
705            return -EINVAL;
706        }
707        effect_param_t *p = (effect_param_t *) pCmdData;
708        *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
709                p->data + p->psize);
710        } break;
711    case EFFECT_CMD_ENABLE:
712        if (pReplyData == NULL || *replySize != sizeof(int)) {
713            return -EINVAL;
714        }
715        if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
716            return -ENOSYS;
717        }
718        pContext->state = EQUALIZER_STATE_ACTIVE;
719        ALOGV("EFFECT_CMD_ENABLE() OK");
720        *(int *)pReplyData = 0;
721        break;
722    case EFFECT_CMD_DISABLE:
723        if (pReplyData == NULL || *replySize != sizeof(int)) {
724            return -EINVAL;
725        }
726        if (pContext->state != EQUALIZER_STATE_ACTIVE) {
727            return -ENOSYS;
728        }
729        pContext->state = EQUALIZER_STATE_INITIALIZED;
730        ALOGV("EFFECT_CMD_DISABLE() OK");
731        *(int *)pReplyData = 0;
732        break;
733    case EFFECT_CMD_SET_DEVICE:
734    case EFFECT_CMD_SET_VOLUME:
735    case EFFECT_CMD_SET_AUDIO_MODE:
736        break;
737    default:
738        ALOGW("Equalizer_command invalid command %d",cmdCode);
739        return -EINVAL;
740    }
741
742    return 0;
743}
744
745extern "C" int Equalizer_getDescriptor(effect_handle_t   self,
746                                    effect_descriptor_t *pDescriptor)
747{
748    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
749
750    if (pContext == NULL || pDescriptor == NULL) {
751        ALOGV("Equalizer_getDescriptor() invalid param");
752        return -EINVAL;
753    }
754
755    memcpy(pDescriptor, &android::gEqualizerDescriptor, sizeof(effect_descriptor_t));
756
757    return 0;
758}
759
760// effect_handle_t interface implementation for equalizer effect
761const struct effect_interface_s gEqualizerInterface = {
762        Equalizer_process,
763        Equalizer_command,
764        Equalizer_getDescriptor,
765        NULL
766};
767
768
769audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
770    tag : AUDIO_EFFECT_LIBRARY_TAG,
771    version : EFFECT_LIBRARY_API_VERSION,
772    name : "Test Equalizer Library",
773    implementor : "The Android Open Source Project",
774    query_num_effects : android::EffectQueryNumberEffects,
775    query_effect : android::EffectQueryEffect,
776    create_effect : android::EffectCreate,
777    release_effect : android::EffectRelease,
778    get_descriptor : android::EffectGetDescriptor,
779};
780