EffectEqualizer.cpp revision be916aa1267e2e6b1c148f51d11bcbbc79cb864c
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//#define LOG_NDEBUG 0
20#include <cutils/log.h>
21#include <assert.h>
22#include <stdlib.h>
23#include <string.h>
24#include <new>
25#include "AudioEqualizer.h"
26#include "AudioBiquadFilter.h"
27#include "AudioFormatAdapter.h"
28#include <media/EffectEqualizerApi.h>
29
30// effect_interface_t interface implementation for equalizer effect
31extern "C" const struct effect_interface_s gEqualizerInterface;
32
33namespace android {
34namespace {
35
36// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
37const effect_descriptor_t gEqualizerDescriptor = {
38        {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
39        {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
40        EFFECT_API_VERSION,
41        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
42        "Graphic Equalizer",
43        "Google Inc.",
44};
45static int gEffectIndex;
46
47/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
48const int kNumBands = 5;
49const uint32_t gFreqs[kNumBands] =      { 50000, 125000, 900000, 3200000, 6300000 };
50const uint32_t gBandwidths[kNumBands] = { 0,     3600,   3600,   2400,    0       };
51
52const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
53    { 300,  gFreqs[0], gBandwidths[0] },
54    { 400,  gFreqs[1], gBandwidths[1] },
55    { 0,    gFreqs[2], gBandwidths[2] },
56    { 200,  gFreqs[3], gBandwidths[3] },
57    { -300, gFreqs[4], gBandwidths[4] }
58};
59
60const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
61    { -600, gFreqs[0], gBandwidths[0] },
62    { 200,  gFreqs[1], gBandwidths[1] },
63    { 400,  gFreqs[2], gBandwidths[2] },
64    { -400, gFreqs[3], gBandwidths[3] },
65    { -600, gFreqs[4], gBandwidths[4] }
66};
67
68const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
69    { 400,  gFreqs[0], gBandwidths[0] },
70    { -400, gFreqs[1], gBandwidths[1] },
71    { 300,  gFreqs[2], gBandwidths[2] },
72    { -400, gFreqs[3], gBandwidths[3] },
73    { 600,  gFreqs[4], gBandwidths[4] }
74};
75
76const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
77    { 700,  gFreqs[0], gBandwidths[0] },
78    { 400,  gFreqs[1], gBandwidths[1] },
79    { -400, gFreqs[2], gBandwidths[2] },
80    { 400,  gFreqs[3], gBandwidths[3] },
81    { 200,  gFreqs[4], gBandwidths[4] }
82};
83
84const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
85    { "Classic", gBandsClassic },
86    { "Jazz",    gBandsJazz    },
87    { "Pop",     gBandsPop     },
88    { "Rock",    gBandsRock    }
89};
90
91/////////////////// END EQ PRESETS /////////////////////////////////////////////
92
93static const size_t kBufferSize = 32;
94
95typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
96
97struct EqualizerContext {
98    const struct effect_interface_s *itfe;
99    effect_config_t config;
100    FormatAdapter adapter;
101    AudioEqualizer * pEqualizer;
102};
103
104
105//--- local function prototypes
106
107int Equalizer_init(EqualizerContext *pContext);
108int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig);
109int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
110int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
111
112
113//
114//--- Effect Library Interface Implementation
115//
116
117extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
118    *pNumEffects = 1;
119    gEffectIndex = 0;
120    return 0;
121} /* end EffectQueryNumberEffects */
122
123extern "C" int EffectQueryNext(effect_descriptor_t *pDescriptor) {
124    if (pDescriptor == NULL) {
125        return -EINVAL;
126    }
127    if (gEffectIndex++ > 0) {
128        return -ENOENT;
129    }
130    memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
131    return 0;
132} /* end EffectQueryNext */
133
134extern "C" int EffectCreate(effect_uuid_t *uuid,
135        effect_interface_t *pInterface) {
136    int ret;
137    int i;
138
139    LOGV("EffectLibCreateEffect start");
140
141    if (pInterface == NULL || uuid == NULL) {
142        return -EINVAL;
143    }
144
145    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
146        return -EINVAL;
147    }
148
149    EqualizerContext *pContext = new EqualizerContext;
150
151    pContext->itfe = &gEqualizerInterface;
152    pContext->pEqualizer = NULL;
153
154    ret = Equalizer_init(pContext);
155    if (ret < 0) {
156        LOGW("EffectLibCreateEffect() init failed");
157        delete pContext;
158        return ret;
159    }
160
161    *pInterface = (effect_interface_t)pContext;
162
163    LOGV("EffectLibCreateEffect %p", pContext);
164
165    return 0;
166
167} /* end EffectCreate */
168
169extern "C" int EffectRelease(effect_interface_t interface) {
170    EqualizerContext * pContext = (EqualizerContext *)interface;
171
172    LOGV("EffectLibReleaseEffect %p", interface);
173    if (pContext == NULL) {
174        return -EINVAL;
175    }
176
177    pContext->pEqualizer->free();
178    delete pContext;
179
180    return 0;
181} /* end EffectRelease */
182
183
184//
185//--- local functions
186//
187
188#define CHECK_ARG(cond) {                     \
189    if (!(cond)) {                            \
190        LOGV("Invalid argument: "#cond);      \
191        return -EINVAL;                       \
192    }                                         \
193}
194
195//----------------------------------------------------------------------------
196// Equalizer_configure()
197//----------------------------------------------------------------------------
198// Purpose: Set input and output audio configuration.
199//
200// Inputs:
201//  pContext:   effect engine context
202//  pConfig:    pointer to effect_config_t structure holding input and output
203//      configuration parameters
204//
205// Outputs:
206//
207//----------------------------------------------------------------------------
208
209int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
210{
211    LOGV("Equalizer_configure start");
212
213    CHECK_ARG(pContext != NULL);
214    CHECK_ARG(pConfig != NULL);
215
216    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
217    CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
218    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
219    CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO));
220    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
221              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
222    CHECK_ARG(pConfig->inputCfg.format == PCM_FORMAT_S7_24
223              || pConfig->inputCfg.format == PCM_FORMAT_S15);
224
225    int channelCount;
226    if (pConfig->inputCfg.channels == CHANNEL_MONO) {
227        channelCount = 1;
228    } else {
229        channelCount = 2;
230    }
231    CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
232
233    pContext->pEqualizer->configure(channelCount,
234                          pConfig->inputCfg.samplingRate);
235
236    pContext->adapter.configure(*pContext->pEqualizer, channelCount,
237                        pConfig->inputCfg.format,
238                        pConfig->outputCfg.accessMode);
239
240    return 0;
241}   // end Equalizer_configure
242
243
244//----------------------------------------------------------------------------
245// Equalizer_init()
246//----------------------------------------------------------------------------
247// Purpose: Initialize engine with default configuration and creates
248//     AudioEqualizer instance.
249//
250// Inputs:
251//  pContext:   effect engine context
252//
253// Outputs:
254//
255//----------------------------------------------------------------------------
256
257int Equalizer_init(EqualizerContext *pContext)
258{
259    int status;
260
261    LOGV("Equalizer_init start");
262
263    CHECK_ARG(pContext != NULL);
264
265    if (pContext->pEqualizer != NULL) {
266        pContext->pEqualizer->free();
267    }
268
269    pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
270    pContext->config.inputCfg.channels = CHANNEL_STEREO;
271    pContext->config.inputCfg.format = PCM_FORMAT_S15;
272    pContext->config.inputCfg.samplingRate = 44100;
273    pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
274    pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
275    pContext->config.inputCfg.bufferProvider.cookie = NULL;
276    pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
277    pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
278    pContext->config.outputCfg.channels = CHANNEL_STEREO;
279    pContext->config.outputCfg.format = PCM_FORMAT_S15;
280    pContext->config.outputCfg.samplingRate = 44100;
281    pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
282    pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
283    pContext->config.outputCfg.bufferProvider.cookie = NULL;
284    pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
285
286    pContext->pEqualizer = AudioEqualizer::CreateInstance(
287        NULL,
288        kNumBands,
289        AudioBiquadFilter::MAX_CHANNELS,
290        44100,
291        gEqualizerPresets,
292        ARRAY_SIZE(gEqualizerPresets));
293
294    for (int i = 0; i < kNumBands; ++i) {
295        pContext->pEqualizer->setFrequency(i, gFreqs[i]);
296        pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
297    }
298
299    pContext->pEqualizer->enable(true);
300
301    Equalizer_configure(pContext, &pContext->config);
302
303    return 0;
304}   // end Equalizer_init
305
306
307//----------------------------------------------------------------------------
308// Equalizer_getParameter()
309//----------------------------------------------------------------------------
310// Purpose:
311// Get a Equalizer parameter
312//
313// Inputs:
314//  pEqualizer       - handle to instance data
315//  pParam           - pointer to parameter
316//  pValue           - pointer to variable to hold retrieved value
317//  pValueSize       - pointer to value size: maximum size as input
318//
319// Outputs:
320//  *pValue updated with parameter value
321//  *pValueSize updated with actual value size
322//
323//
324// Side Effects:
325//
326//----------------------------------------------------------------------------
327
328int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
329{
330    int status = 0;
331    int32_t param = *pParam++;
332    int32_t param2;
333    char *name;
334
335    switch (param) {
336    case EQ_PARAM_NUM_BANDS:
337    case EQ_PARAM_CUR_PRESET:
338    case EQ_PARAM_GET_NUM_OF_PRESETS:
339        if (*pValueSize < sizeof(int16_t)) {
340            return -EINVAL;
341        }
342        *pValueSize = sizeof(int16_t);
343        break;
344
345    case EQ_PARAM_LEVEL_RANGE:
346    case EQ_PARAM_BAND_FREQ_RANGE:
347        if (*pValueSize < 2 * sizeof(int32_t)) {
348            return -EINVAL;
349        }
350        *pValueSize = 2 * sizeof(int32_t);
351        break;
352    case EQ_PARAM_BAND_LEVEL:
353    case EQ_PARAM_GET_BAND:
354    case EQ_PARAM_CENTER_FREQ:
355        if (*pValueSize < sizeof(int32_t)) {
356            return -EINVAL;
357        }
358        *pValueSize = sizeof(int32_t);
359        break;
360
361    case EQ_PARAM_GET_PRESET_NAME:
362        break;
363
364    default:
365        return -EINVAL;
366    }
367
368    switch (param) {
369    case EQ_PARAM_NUM_BANDS:
370        *(int16_t *)pValue = kNumBands;
371        LOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
372        break;
373
374    case EQ_PARAM_LEVEL_RANGE:
375        *(int32_t *)pValue = -9600;
376        *((int32_t *)pValue + 1) = 4800;
377        LOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d", *(int32_t *)pValue, *((int32_t *)pValue + 1));
378        break;
379
380    case EQ_PARAM_BAND_LEVEL:
381        param2 = *pParam;
382        if (param2 >= kNumBands) {
383            status = -EINVAL;
384            break;
385        }
386        *(int32_t *)pValue = pEqualizer->getGain(param2);
387        LOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", param2, *(int32_t *)pValue);
388        break;
389
390    case EQ_PARAM_CENTER_FREQ:
391        param2 = *pParam;
392        if (param2 >= kNumBands) {
393            status = -EINVAL;
394            break;
395        }
396        *(int32_t *)pValue = pEqualizer->getFrequency(param2);
397        LOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d", param2, *(int32_t *)pValue);
398        break;
399
400    case EQ_PARAM_BAND_FREQ_RANGE:
401        param2 = *pParam;
402        if (param2 >= kNumBands) {
403            status = -EINVAL;
404            break;
405        }
406        pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
407        LOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d", param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
408        break;
409
410    case EQ_PARAM_GET_BAND:
411        param2 = *pParam;
412        *(int32_t *)pValue = pEqualizer->getMostRelevantBand(param2);
413        LOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d", param2, *(int32_t *)pValue);
414        break;
415
416    case EQ_PARAM_CUR_PRESET:
417        *(int16_t *)pValue = pEqualizer->getPreset();
418        LOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
419        break;
420
421    case EQ_PARAM_GET_NUM_OF_PRESETS:
422        *(int16_t *)pValue = pEqualizer->getNumPresets();
423        LOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
424        break;
425
426    case EQ_PARAM_GET_PRESET_NAME:
427        param2 = *pParam;
428        if (param2 >= pEqualizer->getNumPresets()) {
429            status = -EINVAL;
430            break;
431        }
432        name = (char *)pValue;
433        strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
434        name[*pValueSize - 1] = 0;
435        *pValueSize = strlen(name) + 1;
436        LOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d", param2, gEqualizerPresets[param2].name, *pValueSize);
437        break;
438
439    default:
440        LOGV("Equalizer_getParameter() invalid param %d", param);
441        status = -EINVAL;
442        break;
443    }
444
445    return status;
446} // end Equalizer_getParameter
447
448
449//----------------------------------------------------------------------------
450// Equalizer_setParameter()
451//----------------------------------------------------------------------------
452// Purpose:
453// Set a Equalizer parameter
454//
455// Inputs:
456//  pEqualizer       - handle to instance data
457//  pParam           - pointer to parameter
458//  pValue           - pointer to value
459//
460// Outputs:
461//
462//
463// Side Effects:
464//
465//----------------------------------------------------------------------------
466
467int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
468{
469    int status = 0;
470    int32_t preset;
471    int32_t band;
472    int32_t level;
473    int32_t param = *pParam++;
474
475
476    switch (param) {
477    case EQ_PARAM_CUR_PRESET:
478        preset = *(int16_t *)pValue;
479
480        LOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
481        if (preset >= pEqualizer->getNumPresets()) {
482            status = -EINVAL;
483            break;
484        }
485        pEqualizer->setPreset(preset);
486        pEqualizer->commit(true);
487        break;
488    case EQ_PARAM_BAND_LEVEL:
489        band =  *pParam;
490        level = *(int32_t *)pValue;
491        LOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
492        if (band >= kNumBands) {
493            status = -EINVAL;
494            break;
495        }
496        pEqualizer->setGain(band, level);
497        pEqualizer->commit(true);
498       break;
499    default:
500        LOGV("setParameter() invalid param %d", param);
501        break;
502    }
503
504    return status;
505} // end Equalizer_setParameter
506
507} // namespace
508} // namespace
509
510
511//
512//--- Effect Control Interface Implementation
513//
514
515extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
516{
517    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
518
519    if (pContext == NULL) {
520        return -EINVAL;
521    }
522    if (inBuffer == NULL || inBuffer->raw == NULL ||
523        outBuffer == NULL || outBuffer->raw == NULL ||
524        inBuffer->frameCount != outBuffer->frameCount) {
525        return -EINVAL;
526    }
527
528    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
529    return 0;
530}   // end Equalizer_process
531
532extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSize,
533        void *pCmdData, int *replySize, void *pReplyData) {
534
535    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
536    int retsize;
537
538    if (pContext == NULL) {
539        return -EINVAL;
540    }
541
542    android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
543
544    LOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
545
546    switch (cmdCode) {
547    case EFFECT_CMD_INIT:
548        if (pReplyData == NULL || *replySize != sizeof(int)) {
549            return -EINVAL;
550        }
551        *(int *) pReplyData = Equalizer_init(pContext);
552        break;
553    case EFFECT_CMD_CONFIGURE:
554        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
555                || pReplyData == NULL || *replySize != sizeof(int)) {
556            return -EINVAL;
557        }
558        *(int *) pReplyData = Equalizer_configure(pContext,
559                (effect_config_t *) pCmdData);
560        break;
561    case EFFECT_CMD_RESET:
562        Equalizer_configure(pContext, &pContext->config);
563        break;
564    case EFFECT_CMD_GET_PARAM: {
565        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
566            pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
567            return -EINVAL;
568        }
569        effect_param_t *p = (effect_param_t *)pCmdData;
570        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
571        p = (effect_param_t *)pReplyData;
572        int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
573        p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
574                p->data + voffset);
575        *replySize = sizeof(effect_param_t) + voffset + p->vsize;
576        LOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
577                *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
578                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
579                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
580
581        } break;
582    case EFFECT_CMD_SET_PARAM: {
583        LOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
584        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
585            pReplyData == NULL || *replySize != sizeof(int32_t)) {
586            return -EINVAL;
587        }
588        effect_param_t *p = (effect_param_t *) pCmdData;
589        *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
590                p->data + p->psize);
591        } break;
592    default:
593        LOGW("Equalizer_command invalid command %d",cmdCode);
594        return -EINVAL;
595    }
596
597    return 0;
598}
599
600// effect_interface_t interface implementation for equalizer effect
601const struct effect_interface_s gEqualizerInterface = {
602        Equalizer_process,
603        Equalizer_command
604};
605
606
607