Echo example and OpenSL ES

445 views
Skip to first unread message

Nacho Ripoll

unread,
Mar 27, 2017, 12:00:31 PM3/27/17
to android-ndk
Hi,

I have been playing around with audio-echo (https://github.com/googlesamples/android-ndk/tree/master/audio-echo) and I have faced some problems. I am trying to attach an equializer to the already published app, I know it will add more latency to the application. I have decided to attach it to the output mix but, despite it seems to be successfully created, it does not work. The code I have added is in red:

AudioPlayer::AudioPlayer(SampleFormat *sampleFormat, SLEngineItf slEngine) :
        sLmillibelMax_(0), sLmillibelMin_(0), eQBandsNo_(0), freeQueue_(nullptr),
        playQueue_(nullptr), devShadowQueue_(nullptr), callback_(nullptr)
{
    SLresult result;
    assert(sampleFormat);
    sampleInfo_ = *sampleFormat;

    SLboolean r[1] = {SL_BOOLEAN_TRUE};
    SLInterfaceID ifac[1] = {SL_IID_EQUALIZER};
    result = (*slEngine)->CreateOutputMix(slEngine, &outputMixObjectItf_, 1,
                                          ifac, r);


    SLASSERT(result);

    // realize the output mix
    result = (*outputMixObjectItf_)->Realize(outputMixObjectItf_, SL_BOOLEAN_FALSE);
    SLASSERT(result);

    // configure audio source
    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
            SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
            DEVICE_SHADOW_BUFFER_QUEUE_LEN };

    SLAndroidDataFormat_PCM_EX format_pcm;
    ConvertToSLSampleFormat(&format_pcm, &sampleInfo_);
    SLDataSource audioSrc = {&loc_bufq, &format_pcm};

    // configure audio sink
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObjectItf_};
    SLDataSink audioSnk = {&loc_outmix, NULL};

    /*
     * create fast path audio player: SL_IID_BUFFERQUEUE and SL_IID_VOLUME interfaces ok,
     * NO others!
     */
    SLInterfaceID  ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
    SLboolean      req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};

    result = (*slEngine)->CreateAudioPlayer(slEngine, &playerObjectItf_,
                                            &audioSrc, &audioSnk,
                                            sizeof(ids)/sizeof(ids[0]), ids, req);

    SLASSERT(result);

    // realize the player
    result = (*playerObjectItf_)->Realize(playerObjectItf_, SL_BOOLEAN_FALSE);
    SLASSERT(result);

    // get the play interface
    result = (*playerObjectItf_)->GetInterface(playerObjectItf_, SL_IID_PLAY, &playItf_);
    SLASSERT(result);

    // get the buffer queue interface
    result = (*playerObjectItf_)->GetInterface(playerObjectItf_, SL_IID_BUFFERQUEUE,
                                             &playBufferQueueItf_);
    SLASSERT(result);

    // get the equalizer interface
    result = (*outputMixObjectItf_)->GetInterface(outputMixObjectItf_,
                                                  SL_IID_EQUALIZER, (void *)
                                                          &slEqualizerItf_);
    SLASSERT(result);


    // register callback on the buffer queue
    result = (*playBufferQueueItf_)->RegisterCallback(playBufferQueueItf_, bqPlayerCallback, this);
    SLASSERT(result);

    result = (*playItf_)->SetPlayState(playItf_, SL_PLAYSTATE_STOPPED);
    SLASSERT(result);

    // create an empty queue to track deviceQueue
    devShadowQueue_ = new AudioQueue(DEVICE_SHADOW_BUFFER_QUEUE_LEN);
    assert(devShadowQueue_);


#ifdef  ENABLE_LOG
    std::string name = "play";
    logFile_ = new AndroidLog(name);
#endif
}

SLresult AudioPlayer::Start(void) {
    SLuint32   state;
    SLresult  result = (*playItf_)->GetPlayState(playItf_, &state);
    if (result != SL_RESULT_SUCCESS) {
        return SL_BOOLEAN_FALSE;
    }
    if(state == SL_PLAYSTATE_PLAYING) {
        return SL_BOOLEAN_TRUE;
    }

    result = (*playItf_)->SetPlayState(playItf_, SL_PLAYSTATE_STOPPED);
    SLASSERT(result);

    result = (*playItf_)->SetPlayState(playItf_, SL_PLAYSTATE_PLAYING);
    SLASSERT(result);

    result = (*slEqualizerItf_)->GetNumberOfBands(slEqualizerItf_,
                                                  &eQBandsNo_);

    SLASSERT(result);

    result = (*slEqualizerItf_)->GetBandLevelRange(slEqualizerItf_,
                                                   &sLmillibelMin_,
                                                   &sLmillibelMax_);
    SLASSERT(result);

    result = (*slEqualizerItf_)->SetBandLevel(slEqualizerItf_, 0,
                                              sLmillibelMax_);
    SLASSERT(result);

    for (int b = 0; b < eQBandsNo_; ++b) {
        result = (*slEqualizerItf_)->SetBandLevel(slEqualizerItf_, b,
                                                  sLmillibelMin_);
        SLASSERT(result);
    }

    result = (*slEqualizerItf_)->SetEnabled(slEqualizerItf_, SL_BOOLEAN_TRUE);
    SLASSERT(result);

    SLboolean ret;
    result = (*slEqualizerItf_)->IsEnabled(slEqualizerItf_, &ret);
    SLASSERT(result);



    // send pre-defined audio buffers to device
    int i = PLAY_KICKSTART_BUFFER_COUNT;
    while(i--) {
        sample_buf *buf;
        if(!playQueue_->front(&buf))    //we have buffers for sure
            break;
        if(SL_RESULT_SUCCESS !=
           (*playBufferQueueItf_)->Enqueue(playBufferQueueItf_, buf, buf->size_))
        {
            LOGE("====failed to enqueue (%d) in %s", i, __FUNCTION__);
            return SL_BOOLEAN_FALSE;
        } else {
            playQueue_->pop();
            devShadowQueue_->push(buf);
        }
    }
    return SL_BOOLEAN_TRUE;
}

Does anyone have any thoughts of what I may be doing wrong?

Thanks in advance for the help.

Gerry Fan

unread,
Mar 27, 2017, 8:08:24 PM3/27/17
to android-ndk
Reply all
Reply to author
Forward
0 new messages