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