Home | History | Annotate | Download | only in libndkaudio
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <assert.h>
     18 
     19 #include <android/log.h>
     20 
     21 #include <SLES/OpenSLES.h>
     22 #include <SLES/OpenSLES_Android.h>
     23 
     24 #include "AudioPlayer.h"
     25 
     26 #include "AudioSource.h"
     27 #include "SystemParams.h"
     28 #include "OpenSLESUtils.h"
     29 
     30 #ifndef NULL
     31 #define NULL 0
     32 #endif
     33 
     34 /*
     35  * OpenSL ES Stuff
     36  */
     37 static const char* TAG = "AudioPlayer";
     38 
     39 // engine interfaces
     40 static SLObjectItf engineObject = 0;
     41 static SLEngineItf engineItf;
     42 
     43 // output mix interfaces
     44 static SLObjectItf outputMixObject = 0;
     45 
     46 // this callback handler is called every time a buffer finishes playing
     47 static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf /*bq*/, void *context)
     48 {
     49     // __android_log_print(ANDROID_LOG_INFO, TAG, "bqPlayerCallback()");
     50     ((ndkaudio::AudioPlayer*)context)->enqueBuffer();
     51 }
     52 
     53 static void OpenSLEngine() {
     54     SLresult result;
     55 
     56     // create engine
     57     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
     58     assert(SL_RESULT_SUCCESS == result);
     59     // __android_log_print(ANDROID_LOG_INFO, TAG, "OpenSLEngine() - engineObject:%p", engineObject);
     60 
     61     // realize the engine
     62     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
     63     // __android_log_print(ANDROID_LOG_INFO, TAG, "Realize() engine result:%s", getSLErrStr(result));
     64    assert(SL_RESULT_SUCCESS == result);
     65 
     66     // get the engine interface, which is needed in order to create other objects
     67     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);
     68     // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() engine:%p result:%s", engineItf, getSLErrStr(result));
     69     assert(SL_RESULT_SUCCESS == result);
     70 
     71     // get the output mixer
     72     result = (*engineItf)->CreateOutputMix(engineItf, &outputMixObject, 0, 0, 0);
     73     // __android_log_print(ANDROID_LOG_INFO, TAG, "CreateOutputMix() mix:%p result:%s", outputMixObject, getSLErrStr(result));
     74     assert(SL_RESULT_SUCCESS == result);
     75 
     76     // realize the output mix
     77     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
     78     // __android_log_print(ANDROID_LOG_INFO, TAG, "Realize() result:%s", getSLErrStr(result));
     79     assert(SL_RESULT_SUCCESS == result);
     80 }
     81 
     82 static void CloseSLEngine() {
     83     __android_log_print(ANDROID_LOG_INFO, TAG, "CloseSLEngine()");
     84 
     85     // destroy output mix object, and invalidate all associated interfaces
     86     if (outputMixObject != NULL) {
     87         (*outputMixObject)->Destroy(outputMixObject);
     88         outputMixObject = NULL;
     89     }
     90 
     91     if (engineObject != NULL) {
     92         (*engineObject)->Destroy(engineObject);
     93         engineObject = NULL;
     94         engineItf = NULL;
     95     }
     96 }
     97 
     98 /*
     99  * AudioPlayer
    100  */
    101 namespace ndkaudio {
    102 
    103 AudioPlayer::AudioPlayer() {
    104     source_ = NULL;
    105 
    106     sampleRate_ = SystemParams::getSampleRate();
    107     numChannels_ = 1;
    108 
    109     numPlayBuffFrames_ = SystemParams::getNumBufferFrames();
    110 
    111     playing_ = false;
    112 
    113     time_ = 0;
    114 
    115     bqPlayerObject_ = NULL;
    116     bq_ = NULL;
    117     bqPlayerPlay_ = NULL;
    118     configItf_ = NULL;
    119 
    120     OpenSLEngine();
    121 }
    122 
    123 AudioPlayer::~AudioPlayer() {
    124     CloseSLEngine();
    125 
    126     delete[] playBuff_;
    127     playBuff_ = 0;
    128 }
    129 
    130 SLresult AudioPlayer::Open(int numChannels, AudioSource* source) {
    131     source_ = source;
    132 
    133     SLresult result;
    134 
    135     numChannels_ = numChannels;
    136 
    137     int internalBuffFactor = 1;
    138 
    139     playBuff_ =
    140             new float[numPlayBuffFrames_ * numChannels_ * internalBuffFactor];
    141     playBuffSizeInBytes_ = numPlayBuffFrames_ * numChannels_ * sizeof(float)
    142             * internalBuffFactor;
    143 
    144     sampleRate_ = SystemParams::getSampleRate();
    145 
    146 //    __android_log_print(ANDROID_LOG_INFO, TAG,
    147 //                        "AudioPlayer::Open(chans:%d, rate:%d)", numChannels,
    148 //                        sampleRate_);
    149 
    150     // configure audio source
    151     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
    152             SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,    // locatorType
    153             1}; // numBuffers
    154 
    155     // SLuint32 chanMask = SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
    156     SLAndroidDataFormat_PCM_EX format_pcm = {SL_ANDROID_DATAFORMAT_PCM_EX,	// formatType
    157             (SLuint32) numChannels_,			// numChannels
    158             (SLuint32)(sampleRate_ * 1000),			// milliSamplesPerSec
    159             32,								// bitsPerSample
    160             32,								// containerSize;
    161             (SLuint32) chanCountToChanMask(numChannels_),  // channelMask
    162             SL_BYTEORDER_LITTLEENDIAN,  // endianness
    163             SL_ANDROID_PCM_REPRESENTATION_FLOAT};  // representation
    164     SLDataSource audioSrc = {&loc_bufq, &format_pcm};
    165 
    166     // configure audio sink
    167     SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,
    168             outputMixObject};
    169     SLDataSink audioSnk = {&loc_outmix, NULL};
    170 
    171     const SLInterfaceID ids[] =
    172             {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
    173     const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    174 
    175     // The Player
    176     result = (*engineItf)->CreateAudioPlayer(engineItf, &bqPlayerObject_,
    177                                              &audioSrc, &audioSnk,
    178                                              sizeof(ids) / sizeof(ids[0]), ids,
    179                                              req);
    180 //    __android_log_print(ANDROID_LOG_INFO, TAG,
    181 //                        "CreateAudioPlayer() result:%s, bqPlayerObject_:%p",
    182 //                        getSLErrStr(result), bqPlayerObject_);
    183     assert(SL_RESULT_SUCCESS == result);
    184 
    185     return result;
    186 }
    187 
    188 void AudioPlayer::Close() {
    189     __android_log_write(ANDROID_LOG_INFO, TAG, "CloseSLPlayer()");
    190 
    191     if (bqPlayerObject_ != NULL) {
    192         (*bqPlayerObject_)->Destroy(bqPlayerObject_);
    193         bqPlayerObject_ = NULL;
    194 
    195         // invalidate any interfaces
    196         bqPlayerPlay_ = NULL;
    197         bq_ = NULL;
    198     }
    199 }
    200 
    201 SLresult AudioPlayer::RealizePlayer() {
    202     SLresult result;
    203 
    204 //    __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer::RealizePlayer()");
    205 
    206     result = (*bqPlayerObject_)->Realize(bqPlayerObject_, SL_BOOLEAN_FALSE);
    207 //    __android_log_print(ANDROID_LOG_INFO, TAG,
    208 //                        "Realize player object result:%s", getSLErrStr(result));
    209     assert(SL_RESULT_SUCCESS == result);
    210 
    211     result = (*bqPlayerObject_)->GetInterface(bqPlayerObject_, SL_IID_PLAY,
    212                                               &bqPlayerPlay_);
    213 //    __android_log_print(ANDROID_LOG_INFO, TAG,
    214 //                        "get player interface result:%s, bqPlayerPlay_:%p",
    215 //                        getSLErrStr(result), bqPlayerPlay_);
    216     assert(SL_RESULT_SUCCESS == result);
    217 
    218     // The BufferQueue
    219     result = (*bqPlayerObject_)->GetInterface(bqPlayerObject_,
    220                                               SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    221                                               &bq_);
    222 //    __android_log_print(ANDROID_LOG_INFO, TAG,
    223 //                        "get bufferqueue interface:%p result:%s", bq_,
    224 //                        getSLErrStr(result));
    225     assert(SL_RESULT_SUCCESS == result);
    226 
    227     // The register BufferQueue callback
    228     result = (*bq_)->RegisterCallback(bq_, bqPlayerCallback, this);
    229 //    __android_log_print(ANDROID_LOG_INFO, TAG, "register callback result:%s",
    230 //                        getSLErrStr(result));
    231     assert(SL_RESULT_SUCCESS == result);
    232 
    233     return result;
    234 }
    235 
    236 SLresult AudioPlayer::RealizeRoutingProxy() {
    237     SLresult result;
    238 
    239     // The Config interface (for routing)
    240     result = (*bqPlayerObject_)->GetInterface(bqPlayerObject_,
    241                                               SL_IID_ANDROIDCONFIGURATION,
    242                                               (void*) &configItf_);
    243 //    __android_log_print(ANDROID_LOG_INFO, TAG, "get Config result:%s",
    244 //                        getSLErrStr(result));
    245     assert(SL_RESULT_SUCCESS == result);
    246 
    247     return result;
    248 }
    249 
    250 SLresult AudioPlayer::Start() {
    251     // __android_log_print(ANDROID_LOG_INFO, TAG, "Start()");
    252     playing_ = true;
    253 
    254     // set the player's state to playing
    255     SLresult result = (*bqPlayerPlay_)->SetPlayState(bqPlayerPlay_,
    256                                                      SL_PLAYSTATE_PLAYING);
    257     // __android_log_print(ANDROID_LOG_INFO, TAG, "SetPlayState() result:%s", getSLErrStr(result));
    258     assert(SL_RESULT_SUCCESS == result);
    259 
    260     enqueBuffer();
    261 
    262     return result;
    263 }
    264 
    265 void AudioPlayer::Stop() {
    266     // __android_log_print(ANDROID_LOG_INFO, TAG, "Stop()");
    267     playing_ = false;
    268 }
    269 
    270 SLresult AudioPlayer::enqueBuffer() {
    271     // __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer::enqueBuffer()");
    272     if (playing_) {
    273         //long dataSizeInSamples = source_->getData(time_++, playBuff_,
    274         //                                          numPlayBuffFrames_,
    275         //                                          source_->getNumChannels());
    276         return (*bq_)->Enqueue(bq_, playBuff_, playBuffSizeInBytes_);
    277     } else {
    278         (*bqPlayerPlay_)->SetPlayState(bqPlayerPlay_, SL_PLAYSTATE_STOPPED);
    279         return 0;
    280     }
    281 }
    282 
    283 } // namespace ndkaudio
    284 
    285