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 
RecCallback(SLRecordItf,void *,SLuint32 event)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 
RecBufferQueueCallback(SLAndroidSimpleBufferQueueItf,void * context)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  */
AudioRecorder()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 
~AudioRecorder()85 AudioRecorder::~AudioRecorder() {}
86 
Open(int numChannels,AudioSink * sink)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 
Close()155 void AudioRecorder::Close() {
156     /* Shutdown OpenSL ES */
157     (*engineObj_)->Destroy(engineObj_);
158     engineObj_ = 0;
159 }
160 
RealizeRecorder()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 
RealizeRoutingProxy()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 
Start()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 
Stop()226 void AudioRecorder::Stop() {
227     recording_ = false;
228 
229     SLresult result;
230     result = (*recorderItf_)->SetRecordState(recorderItf_, SL_RECORDSTATE_STOPPED);
231 }
232 
enqueBuffer()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 
GetRecordBuffer()243 float* AudioRecorder::GetRecordBuffer() {
244     return recBuffer;
245 }
246