From c35fd2e7ba670b1024a920ebf007b0fa1d92c969 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 12 Oct 2010 14:05:56 -0700 Subject: [PATCH] Enable aux effect attachment before the AudioTrack creation. When an OpenSL ES AudioPlayer is playing content from a URI or FD, the AudioTrack it plays on is only created once prefetching is far along enough that the playback properties are known (channel count, word size and sample rate). This happens after Realize() is called on the AudioPlayer. If, before the AudioTrack is created, the SLEffectSendItf interface is used to configure the aux send for that player, there is no AudioTrack to configure. The fix consists in keeping track of the effect the track needs to be attached to, and with what level. Once the track is created, and it gets configured (volume, mutes, channel solos, marker callbacks) we also attach it to the aux effect if necessary. Change-Id: I12230a8cbf7dc3876d3713a006b9702d44e9d6e5 --- opensles/libopensles/IEngine.c | 1 + opensles/libopensles/android_AudioPlayer.cpp | 11 +++++++++++ opensles/libopensles/android_Effect.cpp | 20 ++++++++++++++++++-- opensles/libopensles/sles_allinclusive.h | 4 ++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/opensles/libopensles/IEngine.c b/opensles/libopensles/IEngine.c index 33a33144..a40de1f2 100644 --- a/opensles/libopensles/IEngine.c +++ b/opensles/libopensles/IEngine.c @@ -162,6 +162,7 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer this->mAudioTrack = NULL; // placement new (explicit constructor) (void) new (&this->mSfPlayer) android::sp(); + (void) new (&this->mAuxEffect) android::sp(); #endif // Check the source and sink parameters against generic constraints, diff --git a/opensles/libopensles/android_AudioPlayer.cpp b/opensles/libopensles/android_AudioPlayer.cpp index a120f5eb..3255062f 100644 --- a/opensles/libopensles/android_AudioPlayer.cpp +++ b/opensles/libopensles/android_AudioPlayer.cpp @@ -367,6 +367,14 @@ SLresult audioPlayer_getStreamType(CAudioPlayer* ap, SLint32 *pType) { //----------------------------------------------------------------------------- +void audioPlayer_auxEffectUpdate(CAudioPlayer* ap) { + if ((NULL != ap->mAudioTrack) && (ap->mAuxEffect != 0)) { + android_fxSend_attach(ap, true, ap->mAuxEffect, ap->mVolume.mLevel + ap->mAuxSendLevel); + } +} + + +//----------------------------------------------------------------------------- #ifndef USE_BACKPORT static void sfplayer_prepare(CAudioPlayer *ap, bool lockAP) { @@ -443,6 +451,7 @@ static void sfplayer_handlePrefetchEvent(const int event, const int data1, void* ap->mSfPlayer->startPrefetch_async(); // update the new track with the current settings + audioPlayer_auxEffectUpdate(ap); android_audioPlayer_useEventMask(ap); android_audioPlayer_volumeUpdate(ap); android_audioPlayer_setPlayRate(ap, ap->mPlaybackRate.mRate, false /*lockAP*/); @@ -887,6 +896,7 @@ SLresult android_audioPlayer_create( pAudioPlayer->mAmplFromStereoPos[1] = 1.0f; pAudioPlayer->mDirectLevel = 0; // no attenuation pAudioPlayer->mAmplFromDirectLevel = 1.0f; // matches initial mDirectLevel value + pAudioPlayer->mAuxSendLevel = 0; // initialize interface-specific fields that can be used regardless of whether the interface // is exposed on the AudioPlayer or not @@ -1126,6 +1136,7 @@ SLresult android_audioPlayer_destroy(CAudioPlayer *pAudioPlayer) { // explicit destructor pAudioPlayer->mSfPlayer.~sp(); + pAudioPlayer->mAuxEffect.~sp(); if (pAudioPlayer->mpLock != NULL) { delete pAudioPlayer->mpLock; diff --git a/opensles/libopensles/android_Effect.cpp b/opensles/libopensles/android_Effect.cpp index 259dfa30..1bc0a9e7 100644 --- a/opensles/libopensles/android_Effect.cpp +++ b/opensles/libopensles/android_Effect.cpp @@ -460,10 +460,23 @@ android::status_t android_erev_getParam(android::sp pFx, android::status_t android_fxSend_attach(CAudioPlayer* ap, bool attach, android::sp pFx, SLmillibel sendLevel) { - if ((NULL == ap->mAudioTrack) || (pFx == 0)) { + if (pFx == 0) { return android::INVALID_OPERATION; } + if (NULL == ap->mAudioTrack) { + // the player doesn't have an AudioTrack at the moment, so store this info to use it + // when the AudioTrack becomes available + if (attach) { + ap->mAuxEffect = pFx; + } else { + ap->mAuxEffect.clear(); + } + // we keep track of the send level, independently of the current audio player level + ap->mAuxSendLevel = sendLevel - ap->mVolume.mLevel; + return android::NO_ERROR; + } + if (attach) { android::status_t status = ap->mAudioTrack->attachAuxEffect(pFx->id()); //SL_LOGV("attachAuxEffect(%d) returned %d", pFx->id(), status); @@ -507,8 +520,11 @@ SLresult android_fxSend_attachToAux(CAudioPlayer* ap, SLInterfaceID pUuid, SLboo //----------------------------------------------------------------------------- android::status_t android_fxSend_setSendLevel(CAudioPlayer* ap, SLmillibel sendLevel) { + // we keep track of the send level, independently of the current audio player level + ap->mAuxSendLevel = sendLevel - ap->mVolume.mLevel; + if (NULL == ap->mAudioTrack) { - return android::INVALID_OPERATION; + return android::NO_ERROR; } return ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) ); diff --git a/opensles/libopensles/sles_allinclusive.h b/opensles/libopensles/sles_allinclusive.h index 64ddcc61..117260db 100644 --- a/opensles/libopensles/sles_allinclusive.h +++ b/opensles/libopensles/sles_allinclusive.h @@ -992,6 +992,10 @@ enum AndroidObject_state { android::AudioTrack *mAudioTrack; #ifndef USE_BACKPORT android::sp mSfPlayer; + /** aux effect the AudioTrack will be attached to if aux send enabled */ + android::sp mAuxEffect; + /** send level to aux effect, there's a single aux bus, so there's a single level */ + SLmillibel mAuxSendLevel; #endif /** * Amplification (can be attenuation) factor derived for the VolumeLevel -- 2.11.0