/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* EnvironmentalReverb implementation */

#include "sles_allinclusive.h"
#ifdef ANDROID
#include <audio_effects/effect_environmentalreverb.h>
#endif

// Note: all Set operations use exclusive not poke,
// because SetEnvironmentalReverbProperties is exclusive.
// It is safe for the Get operations to use peek,
// on the assumption that the block copy will atomically
// replace each word of the block.


#if defined(ANDROID)
/**
 * returns true if this interface is not associated with an initialized EnvironmentalReverb effect
 */
static inline bool NO_ENVREVERB(IEnvironmentalReverb* ier) {
    return (ier->mEnvironmentalReverbEffect == 0);
}
#endif


static SLresult IEnvironmentalReverb_SetRoomLevel(SLEnvironmentalReverbItf self, SLmillibel room)
{
    SL_ENTER_INTERFACE

    //if (!(SL_MILLIBEL_MIN <= room && room <= 0)) {
    // comparison (SL_MILLIBEL_MIN <= room) is always true due to range of SLmillibel
    if (!(room <= 0)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.roomLevel = room;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_ROOM_LEVEL, &room);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetRoomLevel(SLEnvironmentalReverbItf self, SLmillibel *pRoom)
{
    SL_ENTER_INTERFACE

    if (NULL == pRoom) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_ROOM_LEVEL, &thiz->mProperties.roomLevel);
            result = android_fx_statusToResult(status);
        }
#endif
        *pRoom = thiz->mProperties.roomLevel;

        interface_unlock_shared(thiz);

    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetRoomHFLevel(
    SLEnvironmentalReverbItf self, SLmillibel roomHF)
{
    SL_ENTER_INTERFACE

    //if (!(SL_MILLIBEL_MIN <= roomHF && roomHF <= 0)) {
    // comparison (SL_MILLIBEL_MIN <= roomHF) is always true due to range of SLmillibel
    if (!(roomHF <= 0)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.roomHFLevel = roomHF;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_ROOM_HF_LEVEL, &roomHF);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetRoomHFLevel(
    SLEnvironmentalReverbItf self, SLmillibel *pRoomHF)
{
    SL_ENTER_INTERFACE

    if (NULL == pRoomHF) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_ROOM_HF_LEVEL, &thiz->mProperties.roomHFLevel);
            result = android_fx_statusToResult(status);
        }
#endif
        *pRoomHF = thiz->mProperties.roomHFLevel;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetDecayTime(
    SLEnvironmentalReverbItf self, SLmillisecond decayTime)
{
    SL_ENTER_INTERFACE

    if (!(100 <= decayTime && decayTime <= 20000)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.decayTime = decayTime;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DECAY_TIME, &decayTime);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetDecayTime(
    SLEnvironmentalReverbItf self, SLmillisecond *pDecayTime)
{
    SL_ENTER_INTERFACE

    if (NULL == pDecayTime) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DECAY_TIME, &thiz->mProperties.decayTime);
            result = android_fx_statusToResult(status);
        }
#endif
        *pDecayTime = thiz->mProperties.decayTime;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetDecayHFRatio(
    SLEnvironmentalReverbItf self, SLpermille decayHFRatio)
{
    SL_ENTER_INTERFACE

    if (!(100 <= decayHFRatio && decayHFRatio <= 2000)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.decayHFRatio = decayHFRatio;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DECAY_HF_RATIO, &decayHFRatio);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetDecayHFRatio(
    SLEnvironmentalReverbItf self, SLpermille *pDecayHFRatio)
{
    SL_ENTER_INTERFACE

    if (NULL == pDecayHFRatio) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DECAY_HF_RATIO, &thiz->mProperties.decayHFRatio);
            result = android_fx_statusToResult(status);
        }
#endif
        *pDecayHFRatio = thiz->mProperties.decayHFRatio;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetReflectionsLevel(
    SLEnvironmentalReverbItf self, SLmillibel reflectionsLevel)
{
    SL_ENTER_INTERFACE

    //if (!(SL_MILLIBEL_MIN <= reflectionsLevel && reflectionsLevel <= 1000)) {
    // comparison (SL_MILLIBEL_MIN <= reflectionsLevel) is always true due to range of SLmillibel
    if (!(reflectionsLevel <= 1000)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.reflectionsLevel = reflectionsLevel;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REFLECTIONS_LEVEL, &reflectionsLevel);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetReflectionsLevel(
    SLEnvironmentalReverbItf self, SLmillibel *pReflectionsLevel)
{
    SL_ENTER_INTERFACE

    if (NULL == pReflectionsLevel) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REFLECTIONS_LEVEL, &thiz->mProperties.reflectionsLevel);
            result = android_fx_statusToResult(status);
        }
#endif
        *pReflectionsLevel = thiz->mProperties.reflectionsLevel;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetReflectionsDelay(
    SLEnvironmentalReverbItf self, SLmillisecond reflectionsDelay)
{
    SL_ENTER_INTERFACE

    if (!(/* 0 <= reflectionsDelay && */ reflectionsDelay <= 300)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.reflectionsDelay = reflectionsDelay;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REFLECTIONS_DELAY, &reflectionsDelay);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetReflectionsDelay(
    SLEnvironmentalReverbItf self, SLmillisecond *pReflectionsDelay)
{
    SL_ENTER_INTERFACE

    if (NULL == pReflectionsDelay) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REFLECTIONS_DELAY, &thiz->mProperties.reflectionsDelay);
            result = android_fx_statusToResult(status);
        }
#endif
        *pReflectionsDelay = thiz->mProperties.reflectionsDelay;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetReverbLevel(
    SLEnvironmentalReverbItf self, SLmillibel reverbLevel)
{
    SL_ENTER_INTERFACE

    //if (!(SL_MILLIBEL_MIN <= reverbLevel && reverbLevel <= 2000)) {
    // comparison (SL_MILLIBEL_MIN <= reverbLevel) is always true due to range of SLmillibel
    if (!(reverbLevel <= 2000)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.reverbLevel = reverbLevel;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REVERB_LEVEL, &reverbLevel);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetReverbLevel(
    SLEnvironmentalReverbItf self, SLmillibel *pReverbLevel)
{
    SL_ENTER_INTERFACE

    if (NULL == pReverbLevel) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REVERB_LEVEL, &thiz->mProperties.reverbLevel);
            result = android_fx_statusToResult(status);
        }
#endif
        *pReverbLevel = thiz->mProperties.reverbLevel;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetReverbDelay(
    SLEnvironmentalReverbItf self, SLmillisecond reverbDelay)
{
    SL_ENTER_INTERFACE

    if (!(/* 0 <= reverbDelay && */ reverbDelay <= 100)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.reverbDelay = reverbDelay;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REVERB_DELAY, &reverbDelay);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetReverbDelay(
    SLEnvironmentalReverbItf self, SLmillisecond *pReverbDelay)
{
    SL_ENTER_INTERFACE

    if (NULL == pReverbDelay) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_REVERB_DELAY, &thiz->mProperties.reverbDelay);
            result = android_fx_statusToResult(status);
        }
#endif
        *pReverbDelay = thiz->mProperties.reverbDelay;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetDiffusion(
    SLEnvironmentalReverbItf self, SLpermille diffusion)
{
    SL_ENTER_INTERFACE

    if (!(0 <= diffusion && diffusion <= 1000)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.diffusion = diffusion;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DIFFUSION, &diffusion);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetDiffusion(SLEnvironmentalReverbItf self,
     SLpermille *pDiffusion)
{
    SL_ENTER_INTERFACE

    if (NULL == pDiffusion) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DIFFUSION, &thiz->mProperties.diffusion);
            result = android_fx_statusToResult(status);
        }
#endif
        *pDiffusion = thiz->mProperties.diffusion;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetDensity(SLEnvironmentalReverbItf self,
    SLpermille density)
{
    SL_ENTER_INTERFACE

    if (!(0 <= density && density <= 1000)) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties.density = density;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DENSITY, &density);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetDensity(SLEnvironmentalReverbItf self,
    SLpermille *pDensity)
{
    SL_ENTER_INTERFACE

    if (NULL == pDensity) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_DENSITY, &thiz->mProperties.density);
            result = android_fx_statusToResult(status);
        }
#endif
        *pDensity = thiz->mProperties.density;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_SetEnvironmentalReverbProperties(SLEnvironmentalReverbItf self,
    const SLEnvironmentalReverbSettings *pProperties)
{
    SL_ENTER_INTERFACE

    // note that it's unnecessary to verify that any level stored inside the "properties" struct
    //  is >= SL_MILLIBEL_MIN before using it, due to range of SLmillibel

    result = SL_RESULT_PARAMETER_INVALID;
    do {
        if (NULL == pProperties)
            break;
        SLEnvironmentalReverbSettings properties = *pProperties;
        if (!(properties.roomLevel <= 0))
            break;
        if (!(properties.roomHFLevel <= 0))
            break;
        if (!(100 <= properties.decayTime && properties.decayTime <= 20000))
            break;
        if (!(100 <= properties.decayHFRatio && properties.decayHFRatio <= 2000))
            break;
        if (!(properties.reflectionsLevel <= 1000))
            break;
        if (!(/* 0 <= properties.reflectionsDelay && */ properties.reflectionsDelay <= 300))
            break;
        if (!(properties.reverbLevel <= 2000))
            break;
        if (!(/* 0 <= properties.reverbDelay && */ properties.reverbDelay <= 100))
            break;
        if (!(0 <= properties.diffusion && properties.diffusion <= 1000))
            break;
        if (!(0 <= properties.density && properties.density <= 1000))
            break;
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_exclusive(thiz);
        thiz->mProperties = properties;
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_PROPERTIES, &properties);
            result = android_fx_statusToResult(status);
        }
#endif
        interface_unlock_exclusive(thiz);
    } while (0);

    SL_LEAVE_INTERFACE
}


static SLresult IEnvironmentalReverb_GetEnvironmentalReverbProperties(
    SLEnvironmentalReverbItf self, SLEnvironmentalReverbSettings *pProperties)
{
    SL_ENTER_INTERFACE

    if (NULL == pProperties) {
        result = SL_RESULT_PARAMETER_INVALID;
    } else {
        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
        interface_lock_shared(thiz);
#if !defined(ANDROID)
        result = SL_RESULT_SUCCESS;
#else
        if (NO_ENVREVERB(thiz)) {
            result = SL_RESULT_CONTROL_LOST;
        } else {
            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
                    REVERB_PARAM_PROPERTIES, &thiz->mProperties);
            result = android_fx_statusToResult(status);
        }
#endif
        *pProperties = thiz->mProperties;

        interface_unlock_shared(thiz);
    }

    SL_LEAVE_INTERFACE
}


static const struct SLEnvironmentalReverbItf_ IEnvironmentalReverb_Itf = {
    IEnvironmentalReverb_SetRoomLevel,
    IEnvironmentalReverb_GetRoomLevel,
    IEnvironmentalReverb_SetRoomHFLevel,
    IEnvironmentalReverb_GetRoomHFLevel,
    IEnvironmentalReverb_SetDecayTime,
    IEnvironmentalReverb_GetDecayTime,
    IEnvironmentalReverb_SetDecayHFRatio,
    IEnvironmentalReverb_GetDecayHFRatio,
    IEnvironmentalReverb_SetReflectionsLevel,
    IEnvironmentalReverb_GetReflectionsLevel,
    IEnvironmentalReverb_SetReflectionsDelay,
    IEnvironmentalReverb_GetReflectionsDelay,
    IEnvironmentalReverb_SetReverbLevel,
    IEnvironmentalReverb_GetReverbLevel,
    IEnvironmentalReverb_SetReverbDelay,
    IEnvironmentalReverb_GetReverbDelay,
    IEnvironmentalReverb_SetDiffusion,
    IEnvironmentalReverb_GetDiffusion,
    IEnvironmentalReverb_SetDensity,
    IEnvironmentalReverb_GetDensity,
    IEnvironmentalReverb_SetEnvironmentalReverbProperties,
    IEnvironmentalReverb_GetEnvironmentalReverbProperties
};

static const SLEnvironmentalReverbSettings IEnvironmentalReverb_default = {
    SL_MILLIBEL_MIN, // roomLevel
    0,               // roomHFLevel
    1000,            // decayTime
    500,             // decayHFRatio
    SL_MILLIBEL_MIN, // reflectionsLevel
    20,              // reflectionsDelay
    SL_MILLIBEL_MIN, // reverbLevel
    40,              // reverbDelay
    1000,            // diffusion
    1000             // density
};

void IEnvironmentalReverb_init(void *self)
{
    IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
    thiz->mItf = &IEnvironmentalReverb_Itf;
    thiz->mProperties = IEnvironmentalReverb_default;
#if defined(ANDROID)
    memset(&thiz->mEnvironmentalReverbDescriptor, 0, sizeof(effect_descriptor_t));
    // placement new (explicit constructor)
    (void) new (&thiz->mEnvironmentalReverbEffect) android::sp<android::AudioEffect>();
#endif
}

void IEnvironmentalReverb_deinit(void *self)
{
#if defined(ANDROID)
    IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
    // explicit destructor
    thiz->mEnvironmentalReverbEffect.~sp();
#endif
}

bool IEnvironmentalReverb_Expose(void *self)
{
#if defined(ANDROID)
    IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
    if (!android_fx_initEffectDescriptor(SL_IID_ENVIRONMENTALREVERB,
            &thiz->mEnvironmentalReverbDescriptor)) {
        SL_LOGE("EnvironmentalReverb initialization failed.");
        return false;
    }
#endif
    return true;
}
