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 #include <assert.h>
     17 
     18 #include <android/log.h>
     19 
     20 #include <SLES/OpenSLES.h>
     21 #include <SLES/OpenSLES_Android.h>
     22 
     23 #include "AudioRecorder.h"
     24 
     25 #include "AudioSink.h"
     26 #include "SystemParams.h"
     27 #include "OpenSLESUtils.h"
     28 
     29 #ifndef NULL
     30 #define NULL 0
     31 #endif
     32 
     33 #define ARRAYSIZE(a) sizeof((a))/sizeof((a)[0])
     34 
     35 using namespace ndkaudio;
     36 
     37 //static const char* const TAG = "AudioRecorder";
     38 
     39 #define NB_BUFFERS_IN_QUEUE 1
     40 
     41 static void RecCallback(SLRecordItf /*recorderItf_*/, void * /*context*/, SLuint32 event)
     42 {
     43     if (SL_RECORDEVENT_HEADATNEWPOS & event) {
     44         // __android_log_print(ANDROID_LOG_INFO, TAG, "SL_RECORDEVENT_HEADATNEWPOS");
     45     }
     46 
     47     if (SL_RECORDEVENT_HEADATMARKER & event) {
     48         // __android_log_print(ANDROID_LOG_INFO, TAG, "SL_RECORDEVENT_HEADATMARKER");
     49     }
     50 
     51     if (SL_RECORDEVENT_BUFFER_FULL & event) {
     52         // __android_log_print(ANDROID_LOG_INFO, TAG, "SL_RECORDEVENT_BUFFER_FULL");
     53     }
     54 }
     55 
     56 #define BUFFER_SIZE_IN_FRAMES	8192
     57 
     58 static float* recBuffer = NULL;
     59 
     60 static void RecBufferQueueCallback(SLAndroidSimpleBufferQueueItf /*queueItf*/, void * context)
     61 {
     62     AudioRecorder* recorder = (AudioRecorder*)context;
     63     // __android_log_print(ANDROID_LOG_INFO, TAG, "RecBufferQueueCallback()");
     64     recorder->enqueBuffer();
     65 }
     66 
     67 /*
     68  * The OpenSL ES code was derived from:
     69  *   frameworks/wilhelm/tests/examples/slesTestRecBuffQueue.cpp
     70  */
     71 AudioRecorder::AudioRecorder()
     72  : sink_(NULL),
     73    recording_(false),
     74    sampleRate_(48000),
     75    numChannels_(0),
     76    numBufferSamples_(0),
     77    engineObj_(NULL),
     78    engineItf_(NULL),
     79    recorderObj_(NULL),
     80    recorderItf_(NULL),
     81    recBuffQueueItf_(NULL),
     82    configItf_(NULL)
     83 {}
     84 
     85 AudioRecorder::~AudioRecorder() {}
     86 
     87 void AudioRecorder::Open(int numChannels, AudioSink* sink) {
     88     sink_ = sink;
     89     numChannels_ = numChannels;
     90     // __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder::Open() - numChannels:%d", numChannels);
     91 
     92     SLresult result;
     93 
     94     numBufferSamples_ = BUFFER_SIZE_IN_FRAMES * numChannels_;
     95     recBuffer = new float[numBufferSamples_];
     96 
     97     SLEngineOption EngineOption[] = {
     98             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
     99     };
    100 
    101     /* Create the OpenSL ES Engine object */
    102     result = slCreateEngine(&engineObj_, 1, EngineOption, 0, NULL, NULL);
    103     assert(SL_RESULT_SUCCESS == result);
    104     // __android_log_print(ANDROID_LOG_INFO, TAG, "slCreateEngine() - engineObj_:%p", engineObj_);
    105 
    106     /* Realizing the SL Engine in synchronous mode. */
    107     result = (*engineObj_)->Realize(engineObj_, SL_BOOLEAN_FALSE);
    108     assert(SL_RESULT_SUCCESS == result);
    109     // __android_log_print(ANDROID_LOG_INFO, TAG, "(*engineObj_)->Realize()");
    110 
    111     result = (*engineObj_)->GetInterface(engineObj_, SL_IID_ENGINE, (void*)&engineItf_);
    112     assert(SL_RESULT_SUCCESS == result);
    113     // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() - engineItf_:%p", engineItf_);
    114 
    115     // Configuration of the recorder
    116     SLboolean required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    117     SLInterfaceID iidArray[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
    118 
    119     SLDataLocator_IODevice ioDevice;
    120     ioDevice.locatorType = SL_DATALOCATOR_IODEVICE;
    121     ioDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
    122     ioDevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
    123     ioDevice.device = NULL;
    124 
    125     SLDataSource recSource;
    126     recSource.pLocator = (void *) &ioDevice;
    127     recSource.pFormat = NULL;
    128 
    129     /* Setup the (OpenSL ES) data sink */
    130     SLDataLocator_AndroidSimpleBufferQueue recBuffQueue;
    131     recBuffQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
    132     recBuffQueue.numBuffers = NB_BUFFERS_IN_QUEUE;
    133 
    134     SLAndroidDataFormat_PCM_EX pcm;
    135     pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
    136     pcm.numChannels = numChannels_;
    137     pcm.sampleRate = sampleRate_ * 1000; // milliHz
    138     pcm.bitsPerSample = 32;
    139     pcm.containerSize = 32;
    140     pcm.channelMask = chanCountToChanMask(numChannels_);
    141     pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    142     pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
    143 
    144     SLDataSink recDest;
    145     recDest.pLocator = (void *) &recBuffQueue;
    146     recDest.pFormat = (void * ) &pcm;
    147 
    148     /* Create the audio recorder */
    149     result = (*engineItf_)->CreateAudioRecorder(engineItf_, &recorderObj_, &recSource, &recDest,
    150             ARRAYSIZE(iidArray), iidArray, required);
    151     assert(SL_RESULT_SUCCESS == result);
    152     // __android_log_print(ANDROID_LOG_INFO, TAG, "CreateAudioRecorder() - recorderObj_:%p", recorderObj_);
    153 }
    154 
    155 void AudioRecorder::Close() {
    156     /* Shutdown OpenSL ES */
    157     (*engineObj_)->Destroy(engineObj_);
    158     engineObj_ = 0;
    159 }
    160 
    161 void AudioRecorder::RealizeRecorder() {
    162     SLresult result;
    163 
    164     /* Realize the recorder in synchronous mode. */
    165     result = (*recorderObj_)->Realize(recorderObj_, SL_BOOLEAN_FALSE);
    166     assert(SL_RESULT_SUCCESS == result);
    167     // __android_log_print(ANDROID_LOG_INFO, TAG, "Recorder realized");
    168 
    169     /* Get the record interface which is implicit */
    170     result = (*recorderObj_)->GetInterface(recorderObj_, SL_IID_RECORD, (void*)&recorderItf_);
    171     assert(SL_RESULT_SUCCESS == result);
    172     // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() recorderItf_:%p", recorderItf_);
    173 
    174     /* Set up the recorder callback to get events during the recording */
    175     // __android_log_print(ANDROID_LOG_INFO, TAG, "SetMarkerPosition()");
    176     result = (*recorderItf_)->SetMarkerPosition(recorderItf_, 2000);
    177     assert(SL_RESULT_SUCCESS == result);
    178 
    179     // __android_log_print(ANDROID_LOG_INFO, TAG, "SetPositionUpdatePeriod()");
    180     result = (*recorderItf_)->SetPositionUpdatePeriod(recorderItf_, 500);
    181     assert(SL_RESULT_SUCCESS == result);
    182 
    183     // __android_log_print(ANDROID_LOG_INFO, TAG, "SetCallbackEventsMask()");
    184     result = (*recorderItf_)->SetCallbackEventsMask(recorderItf_, SL_RECORDEVENT_HEADATMARKER | SL_RECORDEVENT_HEADATNEWPOS);
    185     assert(SL_RESULT_SUCCESS == result);
    186 
    187     // __android_log_print(ANDROID_LOG_INFO, TAG, "RegisterCallback() - Events");
    188     result = (*recorderItf_)->RegisterCallback(recorderItf_, RecCallback, NULL);
    189     assert(SL_RESULT_SUCCESS == result);
    190 
    191     /* Get the buffer queue interface which was explicitly requested */
    192     result = (*recorderObj_)->GetInterface(recorderObj_, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void*)&recBuffQueueItf_);
    193     assert(SL_RESULT_SUCCESS == result);
    194     // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() recBuffQueueItf_:%p", recBuffQueueItf_);
    195 
    196     result = (*recBuffQueueItf_)->RegisterCallback(recBuffQueueItf_, RecBufferQueueCallback, (void*)this);
    197     assert(SL_RESULT_SUCCESS == result);
    198     // __android_log_print(ANDROID_LOG_INFO, TAG, "RegisterCallback() - Buffers");
    199 }
    200 
    201 void AudioRecorder::RealizeRoutingProxy() {
    202     SLresult result;
    203     // The Config interface (for routing)
    204     result = (*recorderObj_)->GetInterface(recorderObj_, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf_);
    205     // __android_log_print(ANDROID_LOG_INFO, TAG, "get Config result:%s", getSLErrStr(result));
    206     assert(SL_RESULT_SUCCESS == result);
    207 }
    208 
    209 void AudioRecorder::Start() {
    210     SLresult result;
    211 
    212     /* Enqueue buffers to map the region of memory allocated to store the recorded data */
    213     // __android_log_print(ANDROID_LOG_INFO, TAG, "Enqueueing buffer");
    214     //int bufferSizeInBytes = BUFFER_SIZE_IN_FRAMES * numChannels_ * sizeof(float);
    215 
    216     enqueBuffer();
    217 
    218     /* ------------------------------------------------------ */
    219     /* Start recording */
    220     // __android_log_print(ANDROID_LOG_INFO, TAG, "Start Recording");
    221     recording_ = true;
    222     result = (*recorderItf_)->SetRecordState(recorderItf_, SL_RECORDSTATE_RECORDING);
    223     assert(SL_RESULT_SUCCESS == result);
    224 }
    225 
    226 void AudioRecorder::Stop() {
    227     recording_ = false;
    228 
    229     SLresult result;
    230     result = (*recorderItf_)->SetRecordState(recorderItf_, SL_RECORDSTATE_STOPPED);
    231 }
    232 
    233 SLresult AudioRecorder::enqueBuffer() {
    234     SLresult result;
    235     int bufferSizeInBytes = numBufferSamples_ * sizeof(float);
    236     // __android_log_print(ANDROID_LOG_INFO, TAG, "Enque %d bytes", bufferSizeInBytes);
    237     result = (*recBuffQueueItf_)->Enqueue(recBuffQueueItf_, recBuffer, bufferSizeInBytes);
    238     assert(SL_RESULT_SUCCESS == result);
    239 
    240     return result;
    241 }
    242 
    243 float* AudioRecorder::GetRecordBuffer() {
    244     return recBuffer;
    245 }
    246