IEffectSend.cpp revision e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037
161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*
261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License.
661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at
761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software
1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and
1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License.
1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */
1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* EffectSend implementation */
1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h"
2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
21510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Maps AUX index to OutputMix interface index
22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic const unsigned char AUX_to_MPH[AUX_MAX] = {
24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    MPH_ENVIRONMENTALREVERB,
25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    MPH_PRESETREVERB
26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten};
27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
28d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic struct EnableLevel *getEnableLevel(IEffectSend *this, const void *pAuxEffect)
2961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
3061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    COutputMix *outputMix = this->mOutputMix;
3161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // Make sure the sink for this player is an output mix
3261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == outputMix)
3361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return NULL;
34510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned aux;
35510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf)
36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_ENVIRONMENTALREVERB;
37510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    else if (pAuxEffect == &outputMix->mPresetReverb.mItf)
38510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_PRESETREVERB;
39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    else
40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(aux < AUX_MAX);
42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // App couldn't have an interface for effect without exposure
43510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = MPH_to_OutputMix[AUX_to_MPH[aux]];
44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (0 > index)
45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned mask = 1 << index;
47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_shared(&outputMix->mObject);
48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint32 state = outputMix->mObject.mInterfaceStates[index];
49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    mask &= outputMix->mObject.mGottenMask;
50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_shared(&outputMix->mObject);
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_EXPOSED:
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDED:
54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDED:
55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDING:
56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:
57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_2:
58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (mask)
59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            return &this->mEnableLevels[aux];
60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:
62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
6461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return NULL;
6561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
6661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
6761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_EnableEffectSend(SLEffectSendItf self,
6861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel)
6961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
70d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0)))
71d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
7261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
7361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
7461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == enableLevel)
7561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
7661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_lock_exclusive(this);
77d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    enableLevel->mEnable = SL_BOOLEAN_FALSE != enable; // normalize
7861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    enableLevel->mSendLevel = initialLevel;
7961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_unlock_exclusive(this);
8061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
8161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
8261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
8361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_IsEnabled(SLEffectSendItf self,
8461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean *pEnable)
8561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
8661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pEnable)
8761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
8861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
8961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
9061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == enableLevel)
9161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
9261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_lock_peek(this);
9361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLboolean enable = enableLevel->mEnable;
9461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_unlock_peek(this);
9561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pEnable = enable;
9661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
9761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
9861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
99d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_SetDirectLevel(SLEffectSendItf self, SLmillibel directLevel)
10061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
101d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0)))
102d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_lock_poke(this);
10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mDirectLevel = directLevel;
10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_unlock_poke(this);
10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
110d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_GetDirectLevel(SLEffectSendItf self, SLmillibel *pDirectLevel)
11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pDirectLevel)
11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
11561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_lock_peek(this);
11661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLmillibel directLevel = this->mDirectLevel;
11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_unlock_peek(this);
11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pDirectLevel = directLevel;
11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
12061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
122e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_SetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
123e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel sendLevel)
12461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
125d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0)))
126d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
12761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
12861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
12961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == enableLevel)
13061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
13161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // EnableEffectSend is exclusive, so this has to be also
13261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_lock_exclusive(this);
13361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    enableLevel->mSendLevel = sendLevel;
13461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_unlock_exclusive(this);
13561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
13661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
13761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
138e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_GetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
139e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel *pSendLevel)
14061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
14161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pSendLevel)
14261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
14361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
14461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
14561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == enableLevel)
14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
14761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_lock_peek(this);
14861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLmillibel sendLevel = enableLevel->mSendLevel;
14961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    interface_unlock_peek(this);
15061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pSendLevel = sendLevel;
15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
15361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
15461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLEffectSendItf_ IEffectSend_Itf = {
15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_EnableEffectSend,
15661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_IsEnabled,
15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetDirectLevel,
15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetDirectLevel,
15961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetSendLevel,
16061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetSendLevel
16161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
16261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
16361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IEffectSend_init(void *self)
16461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
16561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
16661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IEffectSend_Itf;
1676a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    this->mOutputMix = NULL; // CAudioPlayer will need to re-initialize
16861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mDirectLevel = 0;
1696a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    struct EnableLevel *enableLevel = this->mEnableLevels;
1706a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    unsigned aux;
1716a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    for (aux = 0; aux < AUX_MAX; ++aux, ++enableLevel) {
1726a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mEnable = SL_BOOLEAN_FALSE;
1736a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mSendLevel = SL_MILLIBEL_MIN;
1746a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    }
17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
176