1f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean/* 2f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * Copyright (C) 2014 The Android Open Source Project 3f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * 4f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * Licensed under the Apache License, Version 2.0 (the "License"); 5f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * you may not use this file except in compliance with the License. 6f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * You may obtain a copy of the License at 7f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * 8f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * http://www.apache.org/licenses/LICENSE-2.0 9f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * 10f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * Unless required by applicable law or agreed to in writing, software 11f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * distributed under the License is distributed on an "AS IS" BASIS, 12f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * See the License for the specific language governing permissions and 14f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * limitations under the License. 15f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean */ 16f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 17f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean/* Acoustic Echo Cancellation implementation */ 18f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean#include "sles_allinclusive.h" 19f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 20f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean#include <media/EffectsFactoryApi.h> 21f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 22f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean#include <audio_effects/effect_aec.h> 23f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 24f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean/** 25f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean * returns true if this interface is not associated with an initialized AEC effect 26f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean */ 27f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLeanstatic inline bool NO_ECHOCANCEL(IAndroidAcousticEchoCancellation* v) { 28f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean return (v->mAECEffect == 0); 29f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 30f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 310c7022072205ec9790a5b2c1b626096fc4cba74dGlenn Kastenstatic SLresult IAndroidAcousticEchoCancellation_SetEnabled( 320c7022072205ec9790a5b2c1b626096fc4cba74dGlenn Kasten SLAndroidAcousticEchoCancellationItf self, 33f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SLboolean enabled) 34f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean{ 35f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_ENTER_INTERFACE 36f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 37f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 38f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean interface_lock_exclusive(thiz); 39f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean thiz->mEnabled = (SLboolean) enabled; 40f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (NO_ECHOCANCEL(thiz)) { 41f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = SL_RESULT_CONTROL_LOST; 42f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } else { 43f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean android::status_t status = thiz->mAECEffect->setEnabled((bool) thiz->mEnabled); 44f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = android_fx_statusToResult(status); 45f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 46f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean interface_unlock_exclusive(thiz); 47f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 48f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_LEAVE_INTERFACE 49f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 50f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 510c7022072205ec9790a5b2c1b626096fc4cba74dGlenn Kastenstatic SLresult IAndroidAcousticEchoCancellation_IsEnabled( 520c7022072205ec9790a5b2c1b626096fc4cba74dGlenn Kasten SLAndroidAcousticEchoCancellationItf self, 53f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SLboolean *pEnabled) 54f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean{ 55f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_ENTER_INTERFACE 56f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 57f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (NULL == pEnabled) { 58f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = SL_RESULT_PARAMETER_INVALID; 59f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } else { 60f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 61f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean interface_lock_exclusive(thiz); 62f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SLboolean enabled = thiz->mEnabled; 63f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (NO_ECHOCANCEL(thiz)) { 64f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = SL_RESULT_CONTROL_LOST; 65f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } else { 66f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean *pEnabled = (SLboolean) thiz->mAECEffect->getEnabled(); 67f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = SL_RESULT_SUCCESS; 68f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 69f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean interface_unlock_exclusive(thiz); 70f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 71f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 72f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_LEAVE_INTERFACE 73f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 74f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 75f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLeanSLresult IAndroidAcousticEchoCancellation_IsAvailable(SLAndroidAcousticEchoCancellationItf self, 76f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SLboolean *pEnabled) 77f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean{ 78f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_ENTER_INTERFACE 79f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 80f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean *pEnabled = false; 81f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 82f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean uint32_t numEffects = 0; 83f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean int ret = EffectQueryNumberEffects(&numEffects); 84f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (ret != 0) { 85f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean ALOGE("IAndroidAcousticEchoCancellation_IsAvailable() error %d querying number of effects", 86f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean ret); 87f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = SL_RESULT_FEATURE_UNSUPPORTED; 88f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } else { 89f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects); 90f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 91f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean effect_descriptor_t fxDesc; 92f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean for (uint32_t i = 0 ; i < numEffects ; i++) { 93f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (EffectQueryEffect(i, &fxDesc) == 0) { 94f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean ALOGV("effect %d is called %s", i, fxDesc.name); 95f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (memcmp(&fxDesc.type, SL_IID_ANDROIDACOUSTICECHOCANCELLATION, 96f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean sizeof(effect_uuid_t)) == 0) { 97f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean ALOGI("found effect \"%s\" from %s", fxDesc.name, fxDesc.implementor); 98f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean *pEnabled = true; 99f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean break; 100f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 101f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 102f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 103f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean result = SL_RESULT_SUCCESS; 104f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 105f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_LEAVE_INTERFACE 106f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 107f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 108f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLeanstatic const struct SLAndroidAcousticEchoCancellationItf_ IAndroidAcousticEchoCancellation_Itf = { 109f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation_SetEnabled, 110f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation_IsEnabled, 111f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation_IsAvailable 112f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean}; 113f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 114f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLeanvoid IAndroidAcousticEchoCancellation_init(void *self) 115f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean{ 116f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 117f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean thiz->mItf = &IAndroidAcousticEchoCancellation_Itf; 118f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean thiz->mEnabled = SL_BOOLEAN_FALSE; 119f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean memset(&thiz->mAECDescriptor, 0, sizeof(effect_descriptor_t)); 120f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean // placement new (explicit constructor) 121f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean (void) new (&thiz->mAECEffect) android::sp<android::AudioEffect>(); 122f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 123f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 124f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLeanvoid IAndroidAcousticEchoCancellation_deinit(void *self) 125f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean{ 126f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 127f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean // explicit destructor 128f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean thiz->mAECEffect.~sp(); 129f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 130f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean 131f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLeanbool IAndroidAcousticEchoCancellation_Expose(void *self) 132f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean{ 133f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 134f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean if (!android_fx_initEffectDescriptor(SL_IID_ANDROIDACOUSTICECHOCANCELLATION, 135f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean &thiz->mAECDescriptor)) { 136f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean SL_LOGE("Acoustic Echo Cancellation initialization failed."); 137f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean return false; 138f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean } 139f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean return true; 140f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean} 141