1/*
2 * Copyright (C) 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 "Equalizer"
18#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
19//
20#define LOG_NDEBUG 0
21#include <cutils/log.h>
22#include <assert.h>
23#include <stdlib.h>
24#include <string.h>
25#include <new>
26#include "AudioEqualizer.h"
27#include "AudioBiquadFilter.h"
28#include "AudioFormatAdapter.h"
29#include <audio_effects/effect_equalizer.h>
30
31
32// effect_handle_t interface implementation for equalizer effect
33extern "C" const struct effect_interface_s gEqualizerInterface;
34
35enum equalizer_state_e {
36    EQUALIZER_STATE_UNINITIALIZED,
37    EQUALIZER_STATE_INITIALIZED,
38    EQUALIZER_STATE_ACTIVE,
39};
40
41namespace android {
42namespace {
43
44// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
45const effect_descriptor_t gEqualizerDescriptor = {
46        {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
47        {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
48        EFFECT_CONTROL_API_VERSION,
49        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
50        0, // TODO
51        1,
52        "Graphic Equalizer",
53        "The Android Open Source Project",
54};
55
56/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
57const int kNumBands = 5;
58const uint32_t gFreqs[kNumBands] =      { 50000, 125000, 900000, 3200000, 6300000 };
59const uint32_t gBandwidths[kNumBands] = { 0,     3600,   3600,   2400,    0       };
60
61const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
62    { 300,  gFreqs[0], gBandwidths[0] },
63    { 400,  gFreqs[1], gBandwidths[1] },
64    { 0,    gFreqs[2], gBandwidths[2] },
65    { 200,  gFreqs[3], gBandwidths[3] },
66    { -300, gFreqs[4], gBandwidths[4] }
67};
68
69const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
70    { -600, gFreqs[0], gBandwidths[0] },
71    { 200,  gFreqs[1], gBandwidths[1] },
72    { 400,  gFreqs[2], gBandwidths[2] },
73    { -400, gFreqs[3], gBandwidths[3] },
74    { -600, gFreqs[4], gBandwidths[4] }
75};
76
77const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
78    { 400,  gFreqs[0], gBandwidths[0] },
79    { -400, gFreqs[1], gBandwidths[1] },
80    { 300,  gFreqs[2], gBandwidths[2] },
81    { -400, gFreqs[3], gBandwidths[3] },
82    { 600,  gFreqs[4], gBandwidths[4] }
83};
84
85const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
86    { 700,  gFreqs[0], gBandwidths[0] },
87    { 400,  gFreqs[1], gBandwidths[1] },
88    { -400, gFreqs[2], gBandwidths[2] },
89    { 400,  gFreqs[3], gBandwidths[3] },
90    { 200,  gFreqs[4], gBandwidths[4] }
91};
92
93const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
94    { "Classic", gBandsClassic },
95    { "Jazz",    gBandsJazz    },
96    { "Pop",     gBandsPop     },
97    { "Rock",    gBandsRock    }
98};
99
100/////////////////// END EQ PRESETS /////////////////////////////////////////////
101
102static const size_t kBufferSize = 32;
103
104typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
105
106struct EqualizerContext {
107    const struct effect_interface_s *itfe;
108    effect_config_t config;
109    FormatAdapter adapter;
110    AudioEqualizer * pEqualizer;
111    uint32_t state;
112};
113
114//--- local function prototypes
115
116int Equalizer_init(EqualizerContext *pContext);
117int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig);
118int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue);
119int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
120
121
122//
123//--- Effect Library Interface Implementation
124//
125
126extern "C" int EffectCreate(const effect_uuid_t *uuid,
127                            int32_t sessionId,
128                            int32_t ioId,
129                            effect_handle_t *pHandle) {
130    int ret;
131    int i;
132
133    ALOGV("EffectLibCreateEffect start");
134
135    if (pHandle == NULL || uuid == NULL) {
136        return -EINVAL;
137    }
138
139    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
140        return -EINVAL;
141    }
142
143    EqualizerContext *pContext = new EqualizerContext;
144
145    pContext->itfe = &gEqualizerInterface;
146    pContext->pEqualizer = NULL;
147    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
148
149    ret = Equalizer_init(pContext);
150    if (ret < 0) {
151        ALOGW("EffectLibCreateEffect() init failed");
152        delete pContext;
153        return ret;
154    }
155
156    *pHandle = (effect_handle_t)pContext;
157    pContext->state = EQUALIZER_STATE_INITIALIZED;
158
159    ALOGV("EffectLibCreateEffect %p, size %d",
160         pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
161
162    return 0;
163
164} /* end EffectCreate */
165
166extern "C" int EffectRelease(effect_handle_t handle) {
167    EqualizerContext * pContext = (EqualizerContext *)handle;
168
169    ALOGV("EffectLibReleaseEffect %p", handle);
170    if (pContext == NULL) {
171        return -EINVAL;
172    }
173
174    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
175    pContext->pEqualizer->free();
176    delete pContext;
177
178    return 0;
179} /* end EffectRelease */
180
181extern "C" int EffectGetDescriptor(const effect_uuid_t *uuid,
182                                   effect_descriptor_t *pDescriptor) {
183
184    if (pDescriptor == NULL || uuid == NULL){
185        ALOGV("EffectGetDescriptor() called with NULL pointer");
186        return -EINVAL;
187    }
188
189    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
190        *pDescriptor = gEqualizerDescriptor;
191        return 0;
192    }
193
194    return  -EINVAL;
195} /* end EffectGetDescriptor */
196
197
198//
199//--- local functions
200//
201
202#define CHECK_ARG(cond) {                     \
203    if (!(cond)) {                            \
204        ALOGV("Invalid argument: "#cond);      \
205        return -EINVAL;                       \
206    }                                         \
207}
208
209//----------------------------------------------------------------------------
210// Equalizer_setConfig()
211//----------------------------------------------------------------------------
212// Purpose: Set input and output audio configuration.
213//
214// Inputs:
215//  pContext:   effect engine context
216//  pConfig:    pointer to effect_config_t structure holding input and output
217//      configuration parameters
218//
219// Outputs:
220//
221//----------------------------------------------------------------------------
222
223int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig)
224{
225    ALOGV("Equalizer_setConfig start");
226
227    CHECK_ARG(pContext != NULL);
228    CHECK_ARG(pConfig != NULL);
229
230    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
231    CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
232    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
233    CHECK_ARG((pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
234              (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
235    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
236              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
237    CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
238
239    int channelCount;
240    if (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) {
241        channelCount = 1;
242    } else {
243        channelCount = 2;
244    }
245    CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
246
247    pContext->config = *pConfig;
248
249    pContext->pEqualizer->configure(channelCount,
250                          pConfig->inputCfg.samplingRate);
251
252    pContext->adapter.configure(*pContext->pEqualizer, channelCount,
253                        pConfig->inputCfg.format,
254                        pConfig->outputCfg.accessMode);
255
256    return 0;
257}   // end Equalizer_setConfig
258
259//----------------------------------------------------------------------------
260// Equalizer_getConfig()
261//----------------------------------------------------------------------------
262// Purpose: Get input and output audio configuration.
263//
264// Inputs:
265//  pContext:   effect engine context
266//  pConfig:    pointer to effect_config_t structure holding input and output
267//      configuration parameters
268//
269// Outputs:
270//
271//----------------------------------------------------------------------------
272
273void Equalizer_getConfig(EqualizerContext *pContext, effect_config_t *pConfig)
274{
275    *pConfig = pContext->config;
276}   // end Equalizer_getConfig
277
278
279//----------------------------------------------------------------------------
280// Equalizer_init()
281//----------------------------------------------------------------------------
282// Purpose: Initialize engine with default configuration and creates
283//     AudioEqualizer instance.
284//
285// Inputs:
286//  pContext:   effect engine context
287//
288// Outputs:
289//
290//----------------------------------------------------------------------------
291
292int Equalizer_init(EqualizerContext *pContext)
293{
294    int status;
295
296    ALOGV("Equalizer_init start");
297
298    CHECK_ARG(pContext != NULL);
299
300    if (pContext->pEqualizer != NULL) {
301        pContext->pEqualizer->free();
302    }
303
304    pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
305    pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
306    pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
307    pContext->config.inputCfg.samplingRate = 44100;
308    pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
309    pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
310    pContext->config.inputCfg.bufferProvider.cookie = NULL;
311    pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
312    pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
313    pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
314    pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
315    pContext->config.outputCfg.samplingRate = 44100;
316    pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
317    pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
318    pContext->config.outputCfg.bufferProvider.cookie = NULL;
319    pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
320
321    pContext->pEqualizer = AudioEqualizer::CreateInstance(
322        NULL,
323        kNumBands,
324        AudioBiquadFilter::MAX_CHANNELS,
325        44100,
326        gEqualizerPresets,
327        ARRAY_SIZE(gEqualizerPresets));
328
329    for (int i = 0; i < kNumBands; ++i) {
330        pContext->pEqualizer->setFrequency(i, gFreqs[i]);
331        pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
332    }
333
334    pContext->pEqualizer->enable(true);
335
336    Equalizer_setConfig(pContext, &pContext->config);
337
338    return 0;
339}   // end Equalizer_init
340
341
342//----------------------------------------------------------------------------
343// Equalizer_getParameter()
344//----------------------------------------------------------------------------
345// Purpose:
346// Get a Equalizer parameter
347//
348// Inputs:
349//  pEqualizer       - handle to instance data
350//  pParam           - pointer to parameter
351//  pValue           - pointer to variable to hold retrieved value
352//  pValueSize       - pointer to value size: maximum size as input
353//
354// Outputs:
355//  *pValue updated with parameter value
356//  *pValueSize updated with actual value size
357//
358//
359// Side Effects:
360//
361//----------------------------------------------------------------------------
362
363int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue)
364{
365    int status = 0;
366    int32_t param = *pParam++;
367    int32_t param2;
368    char *name;
369
370    switch (param) {
371    case EQ_PARAM_NUM_BANDS:
372    case EQ_PARAM_CUR_PRESET:
373    case EQ_PARAM_GET_NUM_OF_PRESETS:
374    case EQ_PARAM_BAND_LEVEL:
375    case EQ_PARAM_GET_BAND:
376        if (*pValueSize < sizeof(int16_t)) {
377            return -EINVAL;
378        }
379        *pValueSize = sizeof(int16_t);
380        break;
381
382    case EQ_PARAM_LEVEL_RANGE:
383        if (*pValueSize < 2 * sizeof(int16_t)) {
384            return -EINVAL;
385        }
386        *pValueSize = 2 * sizeof(int16_t);
387        break;
388
389    case EQ_PARAM_BAND_FREQ_RANGE:
390        if (*pValueSize < 2 * sizeof(int32_t)) {
391            return -EINVAL;
392        }
393        *pValueSize = 2 * sizeof(int32_t);
394        break;
395
396    case EQ_PARAM_CENTER_FREQ:
397        if (*pValueSize < sizeof(int32_t)) {
398            return -EINVAL;
399        }
400        *pValueSize = sizeof(int32_t);
401        break;
402
403    case EQ_PARAM_GET_PRESET_NAME:
404        break;
405
406    case EQ_PARAM_PROPERTIES:
407        if (*pValueSize < (2 + kNumBands) * sizeof(uint16_t)) {
408            return -EINVAL;
409        }
410        *pValueSize = (2 + kNumBands) * sizeof(uint16_t);
411        break;
412
413    default:
414        return -EINVAL;
415    }
416
417    switch (param) {
418    case EQ_PARAM_NUM_BANDS:
419        *(uint16_t *)pValue = (uint16_t)kNumBands;
420        ALOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
421        break;
422
423    case EQ_PARAM_LEVEL_RANGE:
424        *(int16_t *)pValue = -9600;
425        *((int16_t *)pValue + 1) = 4800;
426        ALOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
427             *(int32_t *)pValue, *((int32_t *)pValue + 1));
428        break;
429
430    case EQ_PARAM_BAND_LEVEL:
431        param2 = *pParam;
432        if (param2 >= kNumBands) {
433            status = -EINVAL;
434            break;
435        }
436        *(int16_t *)pValue = (int16_t)pEqualizer->getGain(param2);
437        ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
438             param2, *(int32_t *)pValue);
439        break;
440
441    case EQ_PARAM_CENTER_FREQ:
442        param2 = *pParam;
443        if (param2 >= kNumBands) {
444            status = -EINVAL;
445            break;
446        }
447        *(int32_t *)pValue = pEqualizer->getFrequency(param2);
448        ALOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
449             param2, *(int32_t *)pValue);
450        break;
451
452    case EQ_PARAM_BAND_FREQ_RANGE:
453        param2 = *pParam;
454        if (param2 >= kNumBands) {
455            status = -EINVAL;
456            break;
457        }
458        pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
459        ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
460             param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
461        break;
462
463    case EQ_PARAM_GET_BAND:
464        param2 = *pParam;
465        *(uint16_t *)pValue = (uint16_t)pEqualizer->getMostRelevantBand(param2);
466        ALOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
467             param2, *(int32_t *)pValue);
468        break;
469
470    case EQ_PARAM_CUR_PRESET:
471        *(uint16_t *)pValue = (uint16_t)pEqualizer->getPreset();
472        ALOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
473        break;
474
475    case EQ_PARAM_GET_NUM_OF_PRESETS:
476        *(uint16_t *)pValue = (uint16_t)pEqualizer->getNumPresets();
477        ALOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
478        break;
479
480    case EQ_PARAM_GET_PRESET_NAME:
481        param2 = *pParam;
482        if (param2 >= pEqualizer->getNumPresets()) {
483            status = -EINVAL;
484            break;
485        }
486        name = (char *)pValue;
487        strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
488        name[*pValueSize - 1] = 0;
489        *pValueSize = strlen(name) + 1;
490        ALOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
491             param2, gEqualizerPresets[param2].name, *pValueSize);
492        break;
493
494    case EQ_PARAM_PROPERTIES: {
495        int16_t *p = (int16_t *)pValue;
496        ALOGV("Equalizer_getParameter() EQ_PARAM_PROPERTIES");
497        p[0] = (int16_t)pEqualizer->getPreset();
498        p[1] = (int16_t)kNumBands;
499        for (int i = 0; i < kNumBands; i++) {
500            p[2 + i] = (int16_t)pEqualizer->getGain(i);
501        }
502    } break;
503
504    default:
505        ALOGV("Equalizer_getParameter() invalid param %d", param);
506        status = -EINVAL;
507        break;
508    }
509
510    return status;
511} // end Equalizer_getParameter
512
513
514//----------------------------------------------------------------------------
515// Equalizer_setParameter()
516//----------------------------------------------------------------------------
517// Purpose:
518// Set a Equalizer parameter
519//
520// Inputs:
521//  pEqualizer       - handle to instance data
522//  pParam           - pointer to parameter
523//  pValue           - pointer to value
524//
525// Outputs:
526//
527//
528// Side Effects:
529//
530//----------------------------------------------------------------------------
531
532int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
533{
534    int status = 0;
535    int32_t preset;
536    int32_t band;
537    int32_t level;
538    int32_t param = *pParam++;
539
540
541    switch (param) {
542    case EQ_PARAM_CUR_PRESET:
543        preset = (int32_t)(*(uint16_t *)pValue);
544
545        ALOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
546        if (preset < 0 || preset >= pEqualizer->getNumPresets()) {
547            status = -EINVAL;
548            break;
549        }
550        pEqualizer->setPreset(preset);
551        pEqualizer->commit(true);
552        break;
553    case EQ_PARAM_BAND_LEVEL:
554        band =  *pParam;
555        level = (int32_t)(*(int16_t *)pValue);
556        ALOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
557        if (band >= kNumBands) {
558            status = -EINVAL;
559            break;
560        }
561        pEqualizer->setGain(band, level);
562        pEqualizer->commit(true);
563       break;
564    case EQ_PARAM_PROPERTIES: {
565        ALOGV("setParameter() EQ_PARAM_PROPERTIES");
566        int16_t *p = (int16_t *)pValue;
567        if ((int)p[0] >= pEqualizer->getNumPresets()) {
568            status = -EINVAL;
569            break;
570        }
571        if (p[0] >= 0) {
572            pEqualizer->setPreset((int)p[0]);
573        } else {
574            if ((int)p[1] != kNumBands) {
575                status = -EINVAL;
576                break;
577            }
578            for (int i = 0; i < kNumBands; i++) {
579                pEqualizer->setGain(i, (int32_t)p[2 + i]);
580            }
581        }
582        pEqualizer->commit(true);
583    } break;
584    default:
585        ALOGV("setParameter() invalid param %d", param);
586        status = -EINVAL;
587        break;
588    }
589
590    return status;
591} // end Equalizer_setParameter
592
593} // namespace
594} // namespace
595
596
597//
598//--- Effect Control Interface Implementation
599//
600
601extern "C" int Equalizer_process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
602{
603    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
604
605    if (pContext == NULL) {
606        return -EINVAL;
607    }
608    if (inBuffer == NULL || inBuffer->raw == NULL ||
609        outBuffer == NULL || outBuffer->raw == NULL ||
610        inBuffer->frameCount != outBuffer->frameCount) {
611        return -EINVAL;
612    }
613
614    if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
615        return -EINVAL;
616    }
617    if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
618        return -ENODATA;
619    }
620
621    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
622
623    return 0;
624}   // end Equalizer_process
625
626extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
627        void *pCmdData, uint32_t *replySize, void *pReplyData) {
628
629    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
630    int retsize;
631
632    if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
633        return -EINVAL;
634    }
635
636    android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
637
638    ALOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
639
640    switch (cmdCode) {
641    case EFFECT_CMD_INIT:
642        if (pReplyData == NULL || *replySize != sizeof(int)) {
643            return -EINVAL;
644        }
645        *(int *) pReplyData = Equalizer_init(pContext);
646        break;
647    case EFFECT_CMD_SET_CONFIG:
648        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
649                || pReplyData == NULL || *replySize != sizeof(int)) {
650            return -EINVAL;
651        }
652        *(int *) pReplyData = Equalizer_setConfig(pContext,
653                (effect_config_t *) pCmdData);
654        break;
655    case EFFECT_CMD_GET_CONFIG:
656        if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
657            return -EINVAL;
658        }
659        Equalizer_getConfig(pContext, (effect_config_t *) pCmdData);
660        break;
661    case EFFECT_CMD_RESET:
662        Equalizer_setConfig(pContext, &pContext->config);
663        break;
664    case EFFECT_CMD_GET_PARAM: {
665        if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
666            pReplyData == NULL || *replySize < (sizeof(effect_param_t) + sizeof(int32_t))) {
667            return -EINVAL;
668        }
669        effect_param_t *p = (effect_param_t *)pCmdData;
670        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
671        p = (effect_param_t *)pReplyData;
672        int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
673        p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
674                p->data + voffset);
675        *replySize = sizeof(effect_param_t) + voffset + p->vsize;
676        ALOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
677                *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
678                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
679                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
680
681        } break;
682    case EFFECT_CMD_SET_PARAM: {
683        ALOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
684             cmdSize, pCmdData, *replySize, pReplyData);
685        if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
686            pReplyData == NULL || *replySize != sizeof(int32_t)) {
687            return -EINVAL;
688        }
689        effect_param_t *p = (effect_param_t *) pCmdData;
690        *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
691                p->data + p->psize);
692        } break;
693    case EFFECT_CMD_ENABLE:
694        if (pReplyData == NULL || *replySize != sizeof(int)) {
695            return -EINVAL;
696        }
697        if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
698            return -ENOSYS;
699        }
700        pContext->state = EQUALIZER_STATE_ACTIVE;
701        ALOGV("EFFECT_CMD_ENABLE() OK");
702        *(int *)pReplyData = 0;
703        break;
704    case EFFECT_CMD_DISABLE:
705        if (pReplyData == NULL || *replySize != sizeof(int)) {
706            return -EINVAL;
707        }
708        if (pContext->state != EQUALIZER_STATE_ACTIVE) {
709            return -ENOSYS;
710        }
711        pContext->state = EQUALIZER_STATE_INITIALIZED;
712        ALOGV("EFFECT_CMD_DISABLE() OK");
713        *(int *)pReplyData = 0;
714        break;
715    case EFFECT_CMD_SET_DEVICE:
716    case EFFECT_CMD_SET_VOLUME:
717    case EFFECT_CMD_SET_AUDIO_MODE:
718        break;
719    default:
720        ALOGW("Equalizer_command invalid command %d",cmdCode);
721        return -EINVAL;
722    }
723
724    return 0;
725}
726
727extern "C" int Equalizer_getDescriptor(effect_handle_t   self,
728                                    effect_descriptor_t *pDescriptor)
729{
730    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
731
732    if (pContext == NULL || pDescriptor == NULL) {
733        ALOGV("Equalizer_getDescriptor() invalid param");
734        return -EINVAL;
735    }
736
737    *pDescriptor = android::gEqualizerDescriptor;
738
739    return 0;
740}
741
742// effect_handle_t interface implementation for equalizer effect
743const struct effect_interface_s gEqualizerInterface = {
744        Equalizer_process,
745        Equalizer_command,
746        Equalizer_getDescriptor,
747        NULL
748};
749
750
751audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
752    tag : AUDIO_EFFECT_LIBRARY_TAG,
753    version : EFFECT_LIBRARY_API_VERSION,
754    name : "Test Equalizer Library",
755    implementor : "The Android Open Source Project",
756    create_effect : android::EffectCreate,
757    release_effect : android::EffectRelease,
758    get_descriptor : android::EffectGetDescriptor,
759};
760