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