Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e886be4 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "Modifications in audio effect engine state management." into gingerbread

parents 9d8bea11 7d850f23
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -223,6 +223,11 @@ typedef struct audio_buffer_s audio_buffer_t;
//          samples as specified in output buffer descriptor. If the buffer descriptor
//          samples as specified in output buffer descriptor. If the buffer descriptor
//          is not specified the function must use either the buffer or the
//          is not specified the function must use either the buffer or the
//          buffer provider function installed by the EFFECT_CMD_CONFIGURE command.
//          buffer provider function installed by the EFFECT_CMD_CONFIGURE command.
//          The effect framework will call the process() function after the EFFECT_CMD_ENABLE
//          command is received and until the EFFECT_CMD_DISABLE is received. When the engine
//          receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully
//          and when done indicate that it is OK to stop calling the process() function by
//          returning the -ENODATA status.
//
//
//    NOTE: the process() function implementation should be "real-time safe" that is
//    NOTE: the process() function implementation should be "real-time safe" that is
//      it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
//      it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
@@ -239,6 +244,8 @@ typedef struct audio_buffer_s audio_buffer_t;
//
//
//    Output:
//    Output:
//        returned value:    0 successful operation
//        returned value:    0 successful operation
//                          -ENODATA the engine has finished the disable phase and the framework
//                                  can stop calling process()
//                          -EINVAL invalid interface handle or
//                          -EINVAL invalid interface handle or
//                                  invalid input/output buffer description
//                                  invalid input/output buffer description
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
+63 −39
Original line number Original line Diff line number Diff line
@@ -17,8 +17,7 @@




#define LOG_TAG "AudioFlinger"
#define LOG_TAG "AudioFlinger"
//
//#define LOG_NDEBUG 0
#define LOG_NDEBUG 0


#include <math.h>
#include <math.h>
#include <signal.h>
#include <signal.h>
@@ -5085,49 +5084,69 @@ void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
    }
    }
}
}


void AudioFlinger::EffectModule::process()
void AudioFlinger::EffectModule::updateState() {
{
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);


    if (mEffectInterface == NULL || mConfig.inputCfg.buffer.raw == NULL || mConfig.outputCfg.buffer.raw == NULL) {
        return;
    }

    if (mState != IDLE) {
        // do 32 bit to 16 bit conversion for auxiliary effect input buffer
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
            AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
                                        mConfig.inputCfg.buffer.s32,
                                        mConfig.inputCfg.buffer.frameCount);
        }

        // TODO: handle effects with buffer provider
        if (mState != ACTIVE) {
    switch (mState) {
    switch (mState) {
            case RESET:
    case RESTART:
        reset_l();
        reset_l();
                mState = STARTING;
        // FALL THROUGH

    case STARTING:
        // clear auxiliary effect input buffer for next accumulation
        // clear auxiliary effect input buffer for next accumulation
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
                    memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
            memset(mConfig.inputCfg.buffer.raw,
                   0,
                   mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
        }
        }
                return;
            case STARTING:
        start_l();
        start_l();
        mState = ACTIVE;
        mState = ACTIVE;
        break;
        break;
    case STOPPING:
    case STOPPING:
        stop_l();
        mDisableWaitCnt = mMaxDisableWaitCnt;
        mState = STOPPED;
        mState = STOPPED;
        break;
        break;
    case STOPPED:
    case STOPPED:
                stop_l();
        // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
        // turn off sequence.
        if (--mDisableWaitCnt == 0) {
            reset_l();
            mState = IDLE;
            mState = IDLE;
        }
        break;
    default: //IDLE , ACTIVE
        break;
    }
}

void AudioFlinger::EffectModule::process()
{
    Mutex::Autolock _l(mLock);

    if (mEffectInterface == NULL ||
            mConfig.inputCfg.buffer.raw == NULL ||
            mConfig.outputCfg.buffer.raw == NULL) {
        return;
        return;
    }
    }

    if (mState == ACTIVE || mState == STOPPING || mState == STOPPED) {
        // do 32 bit to 16 bit conversion for auxiliary effect input buffer
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
            AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
                                        mConfig.inputCfg.buffer.s32,
                                        mConfig.inputCfg.buffer.frameCount);
        }
        }


        // do the actual processing in the effect engine
        // do the actual processing in the effect engine
        (*mEffectInterface)->process(mEffectInterface, &mConfig.inputCfg.buffer, &mConfig.outputCfg.buffer);
        int ret = (*mEffectInterface)->process(mEffectInterface,
                                               &mConfig.inputCfg.buffer,
                                               &mConfig.outputCfg.buffer);

        // force transition to IDLE state when engine is ready
        if (mState == STOPPED && ret == -ENODATA) {
            mDisableWaitCnt = 1;
        }


        // clear auxiliary effect input buffer for next accumulation
        // clear auxiliary effect input buffer for next accumulation
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
@@ -5216,6 +5235,10 @@ status_t AudioFlinger::EffectModule::configure()
    if (status == 0) {
    if (status == 0) {
        status = cmdStatus;
        status = cmdStatus;
    }
    }

    mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
            (1000 * mConfig.outputCfg.buffer.frameCount);

    return status;
    return status;
}
}


@@ -5292,21 +5315,19 @@ status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
        switch (mState) {
        switch (mState) {
        // going from disabled to enabled
        // going from disabled to enabled
        case IDLE:
        case IDLE:
            mState = RESET;
            mState = STARTING;
            break;
        case STOPPED:
            mState = RESTART;
            break;
            break;
        case STOPPING:
        case STOPPING:
            mState = ACTIVE;
            mState = ACTIVE;
            break;
            break;
        case STOPPED:
            mState = STARTING;
            break;


        // going from enabled to disabled
        // going from enabled to disabled
        case RESET:
        case RESTART:
            mState = IDLE;
            break;
        case STARTING:
        case STARTING:
            mState = STOPPED;
            mState = IDLE;
            break;
            break;
        case ACTIVE:
        case ACTIVE:
            mState = STOPPING;
            mState = STOPPING;
@@ -5325,7 +5346,7 @@ status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
bool AudioFlinger::EffectModule::isEnabled()
bool AudioFlinger::EffectModule::isEnabled()
{
{
    switch (mState) {
    switch (mState) {
    case RESET:
    case RESTART:
    case STARTING:
    case STARTING:
    case ACTIVE:
    case ACTIVE:
        return true;
        return true;
@@ -5772,6 +5793,9 @@ void AudioFlinger::EffectChain::process_l()
    for (size_t i = 0; i < size; i++) {
    for (size_t i = 0; i < size; i++) {
        mEffects[i]->process();
        mEffects[i]->process();
    }
    }
    for (size_t i = 0; i < size; i++) {
        mEffects[i]->updateState();
    }
    // if no track is active, input buffer must be cleared here as the mixer process
    // if no track is active, input buffer must be cleared here as the mixer process
    // will not do it
    // will not do it
    if (mSessionId > 0 && activeTracks() == 0) {
    if (mSessionId > 0 && activeTracks() == 0) {
+8 −1
Original line number Original line Diff line number Diff line
@@ -905,7 +905,7 @@ private:


        enum effect_state {
        enum effect_state {
            IDLE,
            IDLE,
            RESET,
            RESTART,
            STARTING,
            STARTING,
            ACTIVE,
            ACTIVE,
            STOPPING,
            STOPPING,
@@ -914,6 +914,7 @@ private:


        int         id() { return mId; }
        int         id() { return mId; }
        void process();
        void process();
        void updateState();
        status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
        status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);


        void reset_l();
        void reset_l();
@@ -948,6 +949,9 @@ private:


    protected:
    protected:


        // Maximum time allocated to effect engines to complete the turn off sequence
        static const uint32_t MAX_DISABLE_TIME_MS = 10000;

        EffectModule(const EffectModule&);
        EffectModule(const EffectModule&);
        EffectModule& operator = (const EffectModule&);
        EffectModule& operator = (const EffectModule&);


@@ -973,6 +977,9 @@ private:
        status_t mStatus;               // initialization status
        status_t mStatus;               // initialization status
        uint32_t mState;                // current activation state (effect_state)
        uint32_t mState;                // current activation state (effect_state)
        Vector< wp<EffectHandle> > mHandles;    // list of client handles
        Vector< wp<EffectHandle> > mHandles;    // list of client handles
        uint32_t mMaxDisableWaitCnt;    // maximum grace period before forcing an effect off after
                                        // sending disable command.
        uint32_t mDisableWaitCnt;       // current process() calls count during disable period.
    };
    };


    // The EffectHandle class implements the IEffect interface. It provides resources
    // The EffectHandle class implements the IEffect interface. It provides resources
+33 −1
Original line number Original line Diff line number Diff line
@@ -30,6 +30,12 @@
// effect_interface_t interface implementation for equalizer effect
// effect_interface_t interface implementation for equalizer effect
extern "C" const struct effect_interface_s gEqualizerInterface;
extern "C" const struct effect_interface_s gEqualizerInterface;


enum equalizer_state_e {
    EQUALIZER_STATE_UNINITIALIZED,
    EQUALIZER_STATE_INITIALIZED,
    EQUALIZER_STATE_ACTIVE,
};

namespace android {
namespace android {
namespace {
namespace {


@@ -100,6 +106,7 @@ struct EqualizerContext {
    effect_config_t config;
    effect_config_t config;
    FormatAdapter adapter;
    FormatAdapter adapter;
    AudioEqualizer * pEqualizer;
    AudioEqualizer * pEqualizer;
    uint32_t state;
};
};


//--- local function prototypes
//--- local function prototypes
@@ -151,6 +158,7 @@ extern "C" int EffectCreate(effect_uuid_t *uuid,


    pContext->itfe = &gEqualizerInterface;
    pContext->itfe = &gEqualizerInterface;
    pContext->pEqualizer = NULL;
    pContext->pEqualizer = NULL;
    pContext->state = EQUALIZER_STATE_UNINITIALIZED;


    ret = Equalizer_init(pContext);
    ret = Equalizer_init(pContext);
    if (ret < 0) {
    if (ret < 0) {
@@ -160,6 +168,7 @@ extern "C" int EffectCreate(effect_uuid_t *uuid,
    }
    }


    *pInterface = (effect_interface_t)pContext;
    *pInterface = (effect_interface_t)pContext;
    pContext->state = EQUALIZER_STATE_INITIALIZED;


    LOGV("EffectLibCreateEffect %p, size %d", pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
    LOGV("EffectLibCreateEffect %p, size %d", pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));


@@ -175,6 +184,7 @@ extern "C" int EffectRelease(effect_interface_t interface) {
        return -EINVAL;
        return -EINVAL;
    }
    }


    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
    pContext->pEqualizer->free();
    pContext->pEqualizer->free();
    delete pContext;
    delete pContext;


@@ -528,6 +538,13 @@ extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuff
        return -EINVAL;
        return -EINVAL;
    }
    }


    if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
        return -EINVAL;
    }
    if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
        return -ENODATA;
    }

    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);


    return 0;
    return 0;
@@ -539,7 +556,7 @@ extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSi
    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
    int retsize;
    int retsize;


    if (pContext == NULL) {
    if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
        return -EINVAL;
        return -EINVAL;
    }
    }


@@ -594,10 +611,25 @@ extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSi
                p->data + p->psize);
                p->data + p->psize);
        } break;
        } break;
    case EFFECT_CMD_ENABLE:
    case EFFECT_CMD_ENABLE:
        if (pReplyData == NULL || *replySize != sizeof(int)) {
            return -EINVAL;
        }
        if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
            return -ENOSYS;
        }
        pContext->state = EQUALIZER_STATE_ACTIVE;
        LOGV("EFFECT_CMD_ENABLE() OK");
        *(int *)pReplyData = 0;
        break;
    case EFFECT_CMD_DISABLE:
    case EFFECT_CMD_DISABLE:
        if (pReplyData == NULL || *replySize != sizeof(int)) {
        if (pReplyData == NULL || *replySize != sizeof(int)) {
            return -EINVAL;
            return -EINVAL;
        }
        }
        if (pContext->state != EQUALIZER_STATE_ACTIVE) {
            return -ENOSYS;
        }
        pContext->state = EQUALIZER_STATE_INITIALIZED;
        LOGV("EFFECT_CMD_DISABLE() OK");
        *(int *)pReplyData = 0;
        *(int *)pReplyData = 0;
        break;
        break;
    case EFFECT_CMD_SET_DEVICE:
    case EFFECT_CMD_SET_DEVICE:
+35 −3
Original line number Original line Diff line number Diff line
@@ -15,8 +15,7 @@
 */
 */


#define LOG_TAG "EffectReverb"
#define LOG_TAG "EffectReverb"
//
//#define LOG_NDEBUG 0
#define LOG_NDEBUG 0
#include <cutils/log.h>
#include <cutils/log.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
@@ -143,6 +142,8 @@ int EffectCreate(effect_uuid_t *uuid,


    module->itfe = &gReverbInterface;
    module->itfe = &gReverbInterface;


    module->context.mState = REVERB_STATE_UNINITIALIZED;

    if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
    if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
        preset = 1;
        preset = 1;
    }
    }
@@ -158,6 +159,8 @@ int EffectCreate(effect_uuid_t *uuid,


    *pInterface = (effect_interface_t) module;
    *pInterface = (effect_interface_t) module;


    module->context.mState = REVERB_STATE_INITIALIZED;

    LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
    LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));


    return 0;
    return 0;
@@ -171,6 +174,8 @@ int EffectRelease(effect_interface_t interface) {
        return -EINVAL;
        return -EINVAL;
    }
    }


    pRvbModule->context.mState = REVERB_STATE_UNINITIALIZED;

    free(pRvbModule);
    free(pRvbModule);
    return 0;
    return 0;
}
}
@@ -195,6 +200,13 @@ static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, aud


    pReverb = (reverb_object_t*) &pRvbModule->context;
    pReverb = (reverb_object_t*) &pRvbModule->context;


    if (pReverb->mState == REVERB_STATE_UNINITIALIZED) {
        return -EINVAL;
    }
    if (pReverb->mState == REVERB_STATE_INITIALIZED) {
        return -ENODATA;
    }

    //if bypassed or the preset forces the signal to be completely dry
    //if bypassed or the preset forces the signal to be completely dry
    if (pReverb->m_bBypass != 0) {
    if (pReverb->m_bBypass != 0) {
        if (inBuffer->raw != outBuffer->raw) {
        if (inBuffer->raw != outBuffer->raw) {
@@ -257,13 +269,15 @@ static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, aud
    return 0;
    return 0;
}
}



static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
        void *pCmdData, int *replySize, void *pReplyData) {
        void *pCmdData, int *replySize, void *pReplyData) {
    reverb_module_t *pRvbModule = (reverb_module_t *) self;
    reverb_module_t *pRvbModule = (reverb_module_t *) self;
    reverb_object_t *pReverb;
    reverb_object_t *pReverb;
    int retsize;
    int retsize;


    if (pRvbModule == NULL) {
    if (pRvbModule == NULL ||
            pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
        return -EINVAL;
        return -EINVAL;
    }
    }


@@ -277,6 +291,9 @@ static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
            return -EINVAL;
            return -EINVAL;
        }
        }
        *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
        *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
        if (*(int *) pReplyData == 0) {
            pRvbModule->context.mState = REVERB_STATE_INITIALIZED;
        }
        break;
        break;
    case EFFECT_CMD_CONFIGURE:
    case EFFECT_CMD_CONFIGURE:
        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
@@ -315,10 +332,25 @@ static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
                cmd->vsize, cmd->data + sizeof(int32_t));
                cmd->vsize, cmd->data + sizeof(int32_t));
        break;
        break;
    case EFFECT_CMD_ENABLE:
    case EFFECT_CMD_ENABLE:
        if (pReplyData == NULL || *replySize != sizeof(int)) {
            return -EINVAL;
        }
        if (pReverb->mState != REVERB_STATE_INITIALIZED) {
            return -ENOSYS;
        }
        pReverb->mState = REVERB_STATE_ACTIVE;
        LOGV("EFFECT_CMD_ENABLE() OK");
        *(int *)pReplyData = 0;
        break;
    case EFFECT_CMD_DISABLE:
    case EFFECT_CMD_DISABLE:
        if (pReplyData == NULL || *replySize != sizeof(int)) {
        if (pReplyData == NULL || *replySize != sizeof(int)) {
            return -EINVAL;
            return -EINVAL;
        }
        }
        if (pReverb->mState != REVERB_STATE_ACTIVE) {
            return -ENOSYS;
        }
        pReverb->mState = REVERB_STATE_INITIALIZED;
        LOGV("EFFECT_CMD_DISABLE() OK");
        *(int *)pReplyData = 0;
        *(int *)pReplyData = 0;
        break;
        break;
    case EFFECT_CMD_SET_DEVICE:
    case EFFECT_CMD_SET_DEVICE:
Loading