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