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