IEffectSend.cpp revision a8179ea15c4ff78db589d742b135649f0eda7ef2
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 21343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten 22343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten/** \brief Maps AUX index to OutputMix interface index */ 23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic const unsigned char AUX_to_MPH[AUX_MAX] = { 25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten MPH_ENVIRONMENTALREVERB, 26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten MPH_PRESETREVERB 27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}; 28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 29343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten 30e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief This is a private function that validates the effect interface specified by the 31e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * application when it calls EnableEffectSend, IsEnabled, SetSendLevel, or GetSendLevel. 32e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * For the interface to be valid, it has to satisfy these requirements: 33e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - object is an audio player (MIDI player is not supported yet) 34e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - audio sink is an output mix 35e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - interface was exposed at object creation time or by DynamicInterface::AddInterface 36e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - interface was "gotten" with Object::GetInterface 37e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten */ 38343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten 39bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenstatic struct EnableLevel *getEnableLevel(IEffectSend *thiz, const void *pAuxEffect) 4061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 41343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten // Make sure this effect send is on an audio player, not a MIDI player 42bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CAudioPlayer *audioPlayer = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 43bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (CAudioPlayer *) thiz->mThis : NULL; 449e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten if (NULL == audioPlayer) { 45343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten return NULL; 469e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } 47f51dba65751107c930759938775b75531ec1f330Glenn Kasten // Get the output mix for this player 48f51dba65751107c930759938775b75531ec1f330Glenn Kasten COutputMix *outputMix = CAudioPlayer_GetOutputMix(audioPlayer); 49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned aux; 509e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) { 51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten aux = AUX_ENVIRONMENTALREVERB; 529e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } else if (pAuxEffect == &outputMix->mPresetReverb.mItf) { 53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten aux = AUX_PRESETREVERB; 549e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } else { 559e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten SL_LOGE("EffectSend on unknown aux effect %p", pAuxEffect); 56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return NULL; 579e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } 58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(aux < AUX_MAX); 59e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // Validate that the application has a valid interface for the effect. The interface must have 60e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // been exposed at object creation time or by DynamicInterface::AddInterface, and it also must 61e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // have been "gotten" with Object::GetInterface. 629e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten unsigned MPH = AUX_to_MPH[aux]; 639e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten int index = MPH_to_OutputMix[MPH]; 649e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten if (0 > index) { 659e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten SL_LOGE("EffectSend aux=%u MPH=%u", aux, MPH); 66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return NULL; 679e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } 68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned mask = 1 << index; 69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_shared(&outputMix->mObject); 70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint32 state = outputMix->mObject.mInterfaceStates[index]; 71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten mask &= outputMix->mObject.mGottenMask; 72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_shared(&outputMix->mObject); 73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: 75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 809e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten if (mask) { 81bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten return &thiz->mEnableLevels[aux]; 829e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } 839e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten SL_LOGE("EffectSend no GetInterface yet"); 84510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 85510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 86a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten SL_LOGE("EffectSend invalid interface state %u", state); 87510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 88510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 8961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return NULL; 9061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 9161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 92faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID) 93172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi/** \brief This is a private function that translates an Android effect framework status code 94172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi * to the SL ES result code used in the EnableEffectSend() function of the SLEffectSendItf 95172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi * interface. 96172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi */ 97172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivistatic SLresult translateEnableFxSendError(android::status_t status) { 98172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi switch (status) { 999e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten case android::NO_ERROR: 1009e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten return SL_RESULT_SUCCESS; 1019e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten case android::INVALID_OPERATION: 1029e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten case android::BAD_VALUE: 1039e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten default: 1049e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten SL_LOGE("EffectSend status %u", status); 1059e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten return SL_RESULT_RESOURCE_ERROR; 106172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 107172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi} 10891bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif 109172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi 110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_EnableEffectSend(SLEffectSendItf self, 11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel) 11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 116ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi //if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) { 117ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi // comparison (SL_MILLIBEL_MIN <= initialLevel) is always true due to range of SLmillibel 118ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi if (!(initialLevel <= 0)) { 119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 121bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 122bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten struct EnableLevel *enableLevel = getEnableLevel(thiz, pAuxEffect); 123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 126bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_lock_exclusive(thiz); 127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten enableLevel->mEnable = SL_BOOLEAN_FALSE != enable; // normalize 128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten enableLevel->mSendLevel = initialLevel; 129faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID) 130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 131172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#else 132172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi // TODO do not repeat querying of CAudioPlayer, done inside getEnableLevel() 133bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 134bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (CAudioPlayer *) thiz->mThis : NULL; 1359e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten // note that if this was a MIDI player, getEnableLevel would have returned NULL 1369e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten assert(NULL != ap); 137172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi // check which effect the send is attached to, attach and set level 1389e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 1399e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten // the initial send level set here is the total energy on the aux bus, 1409e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten // so it must take into account the player volume level 1419e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten if (pAuxEffect == &outputMix->mPresetReverb.mItf) { 1429e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable, 1439e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten outputMix->mPresetReverb.mPresetReverbEffect, 1449e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten initialLevel + ap->mVolume.mLevel)); 1459e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten } else if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) { 1469e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable, 1479e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten outputMix->mEnvironmentalReverb.mEnvironmentalReverbEffect, 1489e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten initialLevel + ap->mVolume.mLevel)); 149172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } else { 1509e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten SL_LOGE("EffectSend unknown aux effect %p", pAuxEffect); 1519e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 152172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 153172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif 154bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_exclusive(thiz); 155ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 15961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 16061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 16261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_IsEnabled(SLEffectSendItf self, 16361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const void *pAuxEffect, SLboolean *pEnable) 16461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 166ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pEnable) { 168ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 170bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 171bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten struct EnableLevel *enableLevel = getEnableLevel(thiz, pAuxEffect); 172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 1739e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten *pEnable = SL_BOOLEAN_FALSE; 174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 175ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 176bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_lock_shared(thiz); 177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLboolean enable = enableLevel->mEnable; 178bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_shared(thiz); 179ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pEnable = enable; 180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 184ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 18561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 18661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 187ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 188d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_SetDirectLevel(SLEffectSendItf self, SLmillibel directLevel) 18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 190ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 191ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 192ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi //if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) { 193ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi // comparison (SL_MILLIBEL_MIN <= directLevel) is always true due to range of SLmillibel 194ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi if (!(directLevel <= 0)) { 195ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 196ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 197bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 198bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_lock_exclusive(thiz); 199bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 200bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (CAudioPlayer *) thiz->mThis : NULL; 201fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi if (NULL != ap) { 202fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi SLmillibel oldDirectLevel = ap->mDirectLevel; 203fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi if (oldDirectLevel != directLevel) { 204fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi ap->mDirectLevel = directLevel; 205fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#if defined(ANDROID) 206172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel); 207bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_exclusive_attributes(thiz, ATTR_GAIN); 208fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#else 209bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_exclusive(thiz); 21091bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif 211fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } else { 212bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_exclusive(thiz); 213fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } 214172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } else { 2159e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten // MIDI player is silently not supported 216bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_exclusive(thiz); 217172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 2189e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten result = SL_RESULT_SUCCESS; 219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 221ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 22261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 22361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 225d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_GetDirectLevel(SLEffectSendItf self, SLmillibel *pDirectLevel) 22661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pDirectLevel) { 230ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 232bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 233bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_lock_shared(thiz); 234bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 235bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (CAudioPlayer *) thiz->mThis : NULL; 236fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi if (NULL != ap) { 237fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi *pDirectLevel = ap->mDirectLevel; 238fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } else { 2399e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten // MIDI player is silently not supported 2409e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten *pDirectLevel = 0; 241fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } 242bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_shared(thiz); 2439e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten result = SL_RESULT_SUCCESS; 244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 24761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 24861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 250e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_SetSendLevel(SLEffectSendItf self, const void *pAuxEffect, 251e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten SLmillibel sendLevel) 25261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 255ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi //if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) { 256ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi // comparison (SL_MILLIBEL_MIN <= sendLevel) is always true due to range of SLmillibel 257ad79bbfd16ba81a45842179178332fbd06ad365eJean-Michel Trivi if (!(sendLevel <= 0)) { 258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 259ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 260bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 261bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten struct EnableLevel *enableLevel = getEnableLevel(thiz, pAuxEffect); 262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 263ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 264ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 265a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten result = SL_RESULT_SUCCESS; 266ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // EnableEffectSend is exclusive, so this has to be also 267bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_lock_exclusive(thiz); 268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten enableLevel->mSendLevel = sendLevel; 269faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID) 270bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 271bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (CAudioPlayer *) thiz->mThis : NULL; 272172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi if (NULL != ap) { 273ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi // the send level set here is the total energy on the aux bus, so it must take 274ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi // into account the player volume level 275ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel); 276172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 277172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif 278bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_exclusive(thiz); 279ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi 280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 28461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 28561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 287e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_GetSendLevel(SLEffectSendItf self, const void *pAuxEffect, 288e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten SLmillibel *pSendLevel) 28961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pSendLevel) { 293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 295bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 296bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten struct EnableLevel *enableLevel = getEnableLevel(thiz, pAuxEffect); 297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 300bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_lock_shared(thiz); 301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLmillibel sendLevel = enableLevel->mSendLevel; 302bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface_unlock_shared(thiz); 303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pSendLevel = sendLevel; 304ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 305ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 306ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 307ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 308ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 31061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 311ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 31261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLEffectSendItf_ IEffectSend_Itf = { 31361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_EnableEffectSend, 31461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_IsEnabled, 31561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_SetDirectLevel, 31661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_GetDirectLevel, 31761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_SetSendLevel, 31861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_GetSendLevel 31961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 32061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 32161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IEffectSend_init(void *self) 32261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 323bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEffectSend *thiz = (IEffectSend *) self; 324bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mItf = &IEffectSend_Itf; 325bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten struct EnableLevel *enableLevel = thiz->mEnableLevels; 3266a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten unsigned aux; 3276a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten for (aux = 0; aux < AUX_MAX; ++aux, ++enableLevel) { 3286a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten enableLevel->mEnable = SL_BOOLEAN_FALSE; 3296a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten enableLevel->mSendLevel = SL_MILLIBEL_MIN; 3306a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } 33161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 332