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