blob: 0a316d8ef5693885387a750c471d57593ea06875 [file] [log] [blame]
Phil Burk64c55f42017-12-13 18:36:53 -08001/*
2 * Copyright 2017 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
Phil Burk6d952912017-12-14 10:10:00 -080017#include <cassert>
18
19#include <SLES/OpenSLES.h>
20#include <SLES/OpenSLES_Android.h>
21
Phil Burk64c55f42017-12-13 18:36:53 -080022#include "oboe/AudioStreamBuilder.h"
23#include "AudioInputStreamOpenSLES.h"
24#include "AudioStreamOpenSLES.h"
Phil Burk6d952912017-12-14 10:10:00 -080025#include "OpenSLESUtilities.h"
Phil Burk64c55f42017-12-13 18:36:53 -080026
27using namespace oboe;
28
29AudioInputStreamOpenSLES::AudioInputStreamOpenSLES(const AudioStreamBuilder &builder)
30 : AudioStreamOpenSLES(builder) {
31}
32
33AudioInputStreamOpenSLES::~AudioInputStreamOpenSLES() {
34}
Phil Burk9a147a12017-12-13 20:23:25 -080035
Phil Burk6d952912017-12-14 10:10:00 -080036#define AUDIO_CHANNEL_COUNT_MAX 30u
37#define SL_ANDROID_UNKNOWN_CHANNELMASK 0
Phil Burk9a147a12017-12-13 20:23:25 -080038
Phil Burk6d952912017-12-14 10:10:00 -080039int AudioInputStreamOpenSLES::chanCountToChanMask(int channelCount) {
Phil Burkd9703b02017-12-14 12:40:48 -080040 // from internal sles_channel_in_mask_from_count(chanCount);
Phil Burk6d952912017-12-14 10:10:00 -080041 switch (channelCount) {
42 case 1:
43 return SL_SPEAKER_FRONT_LEFT;
44 case 2:
45 return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
46 default: {
47 if (channelCount > AUDIO_CHANNEL_COUNT_MAX) {
48 return SL_ANDROID_UNKNOWN_CHANNELMASK;
49 } else {
50 SLuint32 bitfield = (1 << channelCount) - 1;
51 return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield);
52 }
53 }
54 }
Phil Burk9a147a12017-12-13 20:23:25 -080055}
56
Phil Burk9a147a12017-12-13 20:23:25 -080057Result AudioInputStreamOpenSLES::open() {
58
Phil Burk6d952912017-12-14 10:10:00 -080059 Result oboeResult = AudioStreamOpenSLES::open();
60 if (Result::OK != oboeResult) return oboeResult;
61
Phil Burk7040a9d2017-12-15 10:54:38 -080062 SLuint32 bitsPerSample = getBytesPerSample() * kBitsPerByte;
Phil Burk6d952912017-12-14 10:10:00 -080063
64 // configure audio sink
65 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
66 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType
67 static_cast<SLuint32>(mBurstsPerBuffer)}; // numBuffers
68
69 // Define the audio data format.
70 SLDataFormat_PCM format_pcm = {
71 SL_DATAFORMAT_PCM, // formatType
72 (SLuint32) mChannelCount, // numChannels
73 (SLuint32) (mSampleRate * kMillisPerSecond), // milliSamplesPerSec
74 bitsPerSample, // bitsPerSample
75 bitsPerSample, // containerSize;
76 (SLuint32) chanCountToChanMask(mChannelCount), // channelMask
77 getDefaultByteOrder(),
78 };
79
80 SLDataSink audioSink = {&loc_bufq, &format_pcm};
81
82 /**
83 * API 21 (Lollipop) introduced support for floating-point data representation and an extended
84 * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format
85 * type, creating it from our original format.
86 */
87 SLAndroidDataFormat_PCM_EX format_pcm_ex;
88 if (__ANDROID_API__ >= __ANDROID_API_L__) {
89 SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat());
90 // Fill in the format structure.
91 format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation);
92 // Use in place of the previous format.
93 audioSink.pFormat = &format_pcm_ex;
94 }
95
96 // configure audio source
97 SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE,
98 SL_IODEVICE_AUDIOINPUT,
99 SL_DEFAULTDEVICEID_AUDIOINPUT,
100 NULL };
101 SLDataSource audioSrc = {&loc_dev, NULL };
102
Phil Burk7040a9d2017-12-15 10:54:38 -0800103 SLresult result = EngineOpenSLES::getInstance().createAudioRecorder(&mObjectInterface,
Phil Burk6d952912017-12-14 10:10:00 -0800104 &audioSrc,
105 &audioSink);
106 if (SL_RESULT_SUCCESS != result) {
107 LOGE("createAudioRecorder() result:%s", getSLErrStr(result));
108 goto error;
109 }
110
111 // Configure the voice recognition preset, which has no
112 // signal processing, for lower latency.
113 SLAndroidConfigurationItf inputConfig;
114 result = (*mObjectInterface)->GetInterface(mObjectInterface,
115 SL_IID_ANDROIDCONFIGURATION,
116 &inputConfig);
117 if (SL_RESULT_SUCCESS == result) {
118 SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
119 (*inputConfig)->SetConfiguration(inputConfig,
120 SL_ANDROID_KEY_RECORDING_PRESET,
121 &presetValue,
122 sizeof(SLuint32));
123 }
124
125 result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE);
126 if (SL_RESULT_SUCCESS != result) {
127 LOGE("Realize recorder object result:%s", getSLErrStr(result));
128 goto error;
129 }
130
131 result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_RECORD, &mRecordInterface);
132 if (SL_RESULT_SUCCESS != result) {
Phil Burk7040a9d2017-12-15 10:54:38 -0800133 LOGE("GetInterface RECORD result:%s", getSLErrStr(result));
Phil Burk6d952912017-12-14 10:10:00 -0800134 goto error;
135 }
136
137 result = AudioStreamOpenSLES::registerBufferQueueCallback();
138 if (SL_RESULT_SUCCESS != result) {
Phil Burk6d952912017-12-14 10:10:00 -0800139 goto error;
140 }
141
Phil Burk373e6462018-02-07 20:37:17 -0800142 oboeResult = finishOpen();
143 if (oboeResult != oboe::Result::OK) {
144 goto error;
145 }
146
Phil Burk6d952912017-12-14 10:10:00 -0800147 return Result::OK;
Phil Burk7040a9d2017-12-15 10:54:38 -0800148
Phil Burk6d952912017-12-14 10:10:00 -0800149error:
150 return Result::ErrorInternal; // TODO convert error from SLES to OBOE
Phil Burk9a147a12017-12-13 20:23:25 -0800151}
152
153Result AudioInputStreamOpenSLES::close() {
Phil Burk6d952912017-12-14 10:10:00 -0800154 requestStop();
155 mRecordInterface = NULL;
Phil Burk9a147a12017-12-13 20:23:25 -0800156 return AudioStreamOpenSLES::close();
157}
158
Phil Burk6d952912017-12-14 10:10:00 -0800159Result AudioInputStreamOpenSLES::setRecordState(SLuint32 newState) {
160 Result result = Result::OK;
161 LOGD("AudioInputStreamOpenSLES::setRecordState(%d)", newState);
162 if (mRecordInterface == NULL) {
163 return Result::ErrorInvalidState;
164 }
165 SLresult slResult = (*mRecordInterface)->SetRecordState(mRecordInterface, newState);
166 if(SL_RESULT_SUCCESS != slResult) {
167 LOGD("AudioInputStreamOpenSLES::setPlayState() returned %s", getSLErrStr(slResult));
168 result = Result::ErrorInvalidState; // TODO review
169 } else {
170 setState(StreamState::Pausing);
171 }
172 return result;
173}
174
Phil Burk9a147a12017-12-13 20:23:25 -0800175Result AudioInputStreamOpenSLES::requestStart()
176{
Phil Burk6d952912017-12-14 10:10:00 -0800177 LOGD("AudioInputStreamOpenSLES::requestStart()");
178 Result result = setRecordState(SL_RECORDSTATE_RECORDING);
179 if(result != Result::OK) {
180 result = Result::ErrorInvalidState; // TODO review
181 } else {
182 // Enqueue the first buffer so that we have data ready in the callback.
183 enqueueCallbackBuffer(mSimpleBufferQueueInterface);
184 setState(StreamState::Starting);
185 }
186 return result;
Phil Burk9a147a12017-12-13 20:23:25 -0800187}
188
189
190Result AudioInputStreamOpenSLES::requestPause() {
Phil Burk6d952912017-12-14 10:10:00 -0800191 LOGD("AudioInputStreamOpenSLES::requestStop()");
192 Result result = setRecordState(SL_RECORDSTATE_PAUSED);
193 if(result != Result::OK) {
194 result = Result::ErrorInvalidState; // TODO review
195 } else {
196 setState(StreamState::Pausing);
197 }
198 return result;
Phil Burk9a147a12017-12-13 20:23:25 -0800199}
200
201Result AudioInputStreamOpenSLES::requestFlush() {
202 return Result::ErrorUnimplemented; // TODO
203}
204
Phil Burk6d952912017-12-14 10:10:00 -0800205Result AudioInputStreamOpenSLES::requestStop() {
206 LOGD("AudioInputStreamOpenSLES::requestStop()");
207 Result result = setRecordState(SL_RECORDSTATE_STOPPED);
208 if(result != Result::OK) {
209 result = Result::ErrorInvalidState; // TODO review
210 } else {
211 setState(StreamState::Stopping);
212 }
213 return result;
Phil Burk9a147a12017-12-13 20:23:25 -0800214}
215
216Result AudioInputStreamOpenSLES::waitForStateChange(StreamState currentState,
217 StreamState *nextState,
Phil Burk6d952912017-12-14 10:10:00 -0800218 int64_t timeoutNanoseconds) {
219 LOGD("AudioInputStreamOpenSLES::waitForStateChange()");
220 if (mRecordInterface == NULL) {
221 return Result::ErrorInvalidState;
222 }
Phil Burk9a147a12017-12-13 20:23:25 -0800223 return Result::ErrorUnimplemented; // TODO
224}