1 /*
2 * Copyright (C) 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
17 #include "lb2/sound_system_aaudio.h"
18
19 #include <aaudio/AAudio.h>
20
21 #define LOG_TAG "ss_aaudio"
22 #include "lb2/logging.h"
23 #include "lb2/oboe/src/aaudio/AAudioLoader.h"
24 #include "lb2/util.h"
25
26 namespace {
27
28 class Stream {
29 public:
30 explicit Stream(AAudioStream *stream);
31 Stream(const Stream&) = delete;
32 Stream& operator=(const Stream&) = delete;
33 ~Stream();
34
getChannelCount() const35 int getChannelCount() const { return mChannelCount; }
getFramesPerBurst() const36 int getFramesPerBurst() const { return mFramesPerBurst; }
37 int getSamplingRateHz();
38 ssize_t read(AudioBufferView<sample_t> buffer);
39 bool setBufferFrameCount(int numFrames);
40 bool start();
41 bool stop();
42
43 private:
44 AAudioLoader *mAAudio;
45 AAudioStream *mAAStream;
46 const int mChannelCount;
47 const int mFramesPerBurst;
48 };
49
Stream(AAudioStream * stream)50 Stream::Stream(AAudioStream *stream)
51 : mAAudio(AAudioLoader::getInstance()),
52 mAAStream(stream),
53 mChannelCount(mAAudio->stream_getChannelCount(stream)),
54 mFramesPerBurst(mAAudio->stream_getFramesPerBurst(stream)) {
55 ALOGV("Created stream, channel count %d, frames per burst: %d",
56 mChannelCount, mFramesPerBurst);
57 }
58
~Stream()59 Stream::~Stream() {
60 aaudio_result_t result = mAAudio->stream_close(mAAStream);
61 if (result != AAUDIO_OK) {
62 ALOGE("Failed to close stream %s (%d)", mAAudio->convertResultToText(result), result);
63 }
64 }
65
getSamplingRateHz()66 int Stream::getSamplingRateHz() {
67 return mAAudio->stream_getSampleRate(mAAStream);
68 }
69
read(AudioBufferView<sample_t> buffer)70 ssize_t Stream::read(AudioBufferView<sample_t> buffer) {
71 ATRACE_CALL();
72 aaudio_result_t result = mAAudio->stream_read(
73 mAAStream, buffer.getData(), buffer.getFrameCount(), 0 /* timeout */);
74 if (result < 0) {
75 ALOGE("Failed to read from the stream %s (%d)",
76 mAAudio->convertResultToText(result), result);
77 }
78 return result;
79 }
80
setBufferFrameCount(int numFrames)81 bool Stream::setBufferFrameCount(int numFrames) {
82 aaudio_result_t result = mAAudio->stream_setBufferSize(mAAStream, numFrames);
83 if (result < 0) {
84 ALOGE("Failed to set frame buffer size to %d frames: %s (%d)",
85 numFrames, mAAudio->convertResultToText(result), result);
86 }
87 return result >= 0;
88 }
89
start()90 bool Stream::start() {
91 aaudio_result_t result = mAAudio->stream_requestStart(mAAStream);
92 if (result != AAUDIO_OK) {
93 ALOGE("Failed to start the stream %s (%d)", mAAudio->convertResultToText(result), result);
94 return false;
95 }
96 return true;
97 }
98
stop()99 bool Stream::stop() {
100 aaudio_result_t result = mAAudio->stream_requestStop(mAAStream);
101 if (result != AAUDIO_OK) {
102 ALOGE("Failed to stop the stream %s (%d)", mAAudio->convertResultToText(result), result);
103 return false;
104 }
105 return true;
106 }
107
108
109 class StreamBuilder {
110 public:
111 explicit StreamBuilder(AAudioStreamBuilder *builder);
112 StreamBuilder(const StreamBuilder&) = delete;
113 StreamBuilder& operator=(const StreamBuilder&) = delete;
114 ~StreamBuilder();
115
116 std::unique_ptr<Stream> makeStream();
setCallbacks(AAudioStream_dataCallback dataCb,AAudioStream_errorCallback errorCb,void * userData)117 void setCallbacks(AAudioStream_dataCallback dataCb,
118 AAudioStream_errorCallback errorCb,
119 void *userData) {
120 mAAudio->builder_setDataCallback(mAABuilder, dataCb, userData);
121 mAAudio->builder_setErrorCallback(mAABuilder, errorCb, userData);
122 }
setChannelCount(int32_t channelCount)123 void setChannelCount(int32_t channelCount) {
124 mAAudio->builder_setChannelCount(mAABuilder, channelCount);
125 }
setDirection(aaudio_direction_t direction)126 void setDirection(aaudio_direction_t direction) {
127 mAAudio->builder_setDirection(mAABuilder, direction);
128 }
setFormat(aaudio_format_t format)129 void setFormat(aaudio_format_t format) {
130 mAAudio->builder_setFormat(mAABuilder, format);
131 }
setPerformanceMode(aaudio_performance_mode_t mode)132 void setPerformanceMode(aaudio_performance_mode_t mode) {
133 mAAudio->builder_setPerformanceMode(mAABuilder, mode);
134 }
setSampleRate(int32_t sampleRate)135 void setSampleRate(int32_t sampleRate) {
136 mAAudio->builder_setSampleRate(mAABuilder, sampleRate);
137 }
setSharingMode(aaudio_sharing_mode_t sharingMode)138 void setSharingMode(aaudio_sharing_mode_t sharingMode) {
139 mAAudio->builder_setSharingMode(mAABuilder, sharingMode);
140 }
141
142 private:
143 AAudioLoader *mAAudio;
144 AAudioStreamBuilder *mAABuilder;
145 };
146
StreamBuilder(AAudioStreamBuilder * builder)147 StreamBuilder::StreamBuilder(AAudioStreamBuilder *builder)
148 : mAAudio(AAudioLoader::getInstance()),
149 mAABuilder(builder) {
150 }
151
~StreamBuilder()152 StreamBuilder::~StreamBuilder() {
153 aaudio_result_t result = mAAudio->builder_delete(mAABuilder);
154 if (result != AAUDIO_OK) {
155 ALOGE("Failed to delete stream builder %s (%d)",
156 mAAudio->convertResultToText(result), result);
157 }
158 }
159
makeStream()160 std::unique_ptr<Stream> StreamBuilder::makeStream() {
161 AAudioStream *stream = nullptr;
162 aaudio_result_t result = mAAudio->builder_openStream(mAABuilder, &stream);
163 if (result != AAUDIO_OK || stream == nullptr) {
164 ALOGE("Failed to create stream %s (%d) %p",
165 mAAudio->convertResultToText(result), result, stream);
166 return nullptr;
167 }
168 return std::unique_ptr<Stream>(new Stream(stream));
169 }
170
makeStreamBuilder()171 std::unique_ptr<StreamBuilder> makeStreamBuilder() {
172 AAudioStreamBuilder *builder = nullptr;
173 aaudio_result_t result = AAudioLoader::getInstance()->createStreamBuilder(&builder);
174 if (result != AAUDIO_OK || builder == nullptr) {
175 ALOGE("Failed to create stream builder %s (%d) %p",
176 AAudioLoader::getInstance()->convertResultToText(result), result, builder);
177 return nullptr;
178 }
179 return std::unique_ptr<StreamBuilder>(new StreamBuilder(builder));
180 }
181
getAAudioPerfMode(PerformanceMode performanceMode)182 aaudio_performance_mode_t getAAudioPerfMode(PerformanceMode performanceMode) {
183 switch (performanceMode) {
184 case PerformanceMode::NONE: return AAUDIO_PERFORMANCE_MODE_NONE;
185 case PerformanceMode::DEFAULT: // The testing mode we should use by default is low latency.
186 case PerformanceMode::LATENCY:
187 case PerformanceMode::LATENCY_EFFECTS: return AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
188 case PerformanceMode::POWER_SAVING: return AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
189 }
190 ALOGE("Invalid performance mode value %d", static_cast<int>(performanceMode));
191 return AAUDIO_PERFORMANCE_MODE_NONE;
192 }
193
calculateBufferSizeInFrames(int burstSizeInFrames,int bufferSizeMs,int samplingRateHz)194 int calculateBufferSizeInFrames(int burstSizeInFrames, int bufferSizeMs, int samplingRateHz) {
195 const int desiredBufferSizeInFrames = wholeMultiplier(
196 bufferSizeMs * samplingRateHz, MS_PER_SECOND);
197 // Figure out how many bursts we need to cover the desired buffer size completely, and multiply
198 // that number by the burst size.
199 return wholeMultiplier(desiredBufferSizeInFrames, burstSizeInFrames) * burstSizeInFrames;
200 }
201
202
203 class Player {
204 public:
205 using ErrorCallback = std::function<void(aaudio_result_t)>;
206
Player()207 Player() {}
208 Player(const Player&) = delete;
209 Player& operator=(const Player&) = delete;
~Player()210 ~Player() { shutdown(); }
211
212 bool probeDefaults(
213 PerformanceMode performanceMode, int *samplingRate, int *playerBufferFrameCount);
214 bool init(const TestContext *testCtx,
215 SoundSystem::WriteCallback writeClb,
216 ErrorCallback errorClb);
217 void shutdown();
218
219 private:
220 // Output stream buffer size in milliseconds. Larger values increase
221 // latency, but reduce possibility of glitching. AAudio operates in
222 // 2ms "bursts" by default (controlled by "aaudio.hw_burst_min_usec"
223 // system property), so 4 ms is 2 bursts--"double buffering".
224 // TODO: May actually read the property value to derive this
225 // value, but property reading isn't exposed in NDK.
226 static constexpr int MINIMUM_STREAM_BUFFER_SIZE_MS = 4;
227
228 static aaudio_data_callback_result_t aaudioDataCallback(AAudioStream *stream,
229 void *userData,
230 void *audioData,
231 int32_t numFrames);
232 static void aaudioErrorCallback(AAudioStream *stream,
233 void *userData,
234 aaudio_result_t error);
235
236 std::unique_ptr<StreamBuilder> createBuilder(PerformanceMode performanceMode);
237
238 const TestContext *mTestCtx;
239 std::unique_ptr<Stream> mStream;
240 SoundSystem::WriteCallback mWriteCallback;
241 ErrorCallback mErrorCallback;
242 };
243
createBuilder(PerformanceMode performanceMode)244 std::unique_ptr<StreamBuilder> Player::createBuilder(PerformanceMode performanceMode) {
245 std::unique_ptr<StreamBuilder> builder = makeStreamBuilder();
246 if (builder) {
247 builder->setDirection(AAUDIO_DIRECTION_OUTPUT);
248 builder->setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
249 builder->setPerformanceMode(getAAudioPerfMode(performanceMode));
250 static_assert(sizeof(sample_t) == sizeof(int16_t), "sample format must be int16");
251 builder->setFormat(AAUDIO_FORMAT_PCM_I16);
252 builder->setCallbacks(&Player::aaudioDataCallback, &Player::aaudioErrorCallback, this);
253 }
254 return builder;
255 }
256
probeDefaults(PerformanceMode performanceMode,int * samplingRate,int * playerBufferFrameCount)257 bool Player::probeDefaults(
258 PerformanceMode performanceMode, int *samplingRate, int *playerBufferFrameCount) {
259 std::unique_ptr<StreamBuilder> builder = createBuilder(performanceMode);
260 if (!builder) return false;
261 mStream = builder->makeStream();
262 if (!mStream) return false;
263 *samplingRate = mStream->getSamplingRateHz();
264 *playerBufferFrameCount = calculateBufferSizeInFrames(
265 mStream->getFramesPerBurst(), MINIMUM_STREAM_BUFFER_SIZE_MS, *samplingRate);
266 return true;
267 }
268
init(const TestContext * testCtx,SoundSystem::WriteCallback writeClb,ErrorCallback errorClb)269 bool Player::init(const TestContext *testCtx,
270 SoundSystem::WriteCallback writeClb,
271 ErrorCallback errorClb) {
272 mTestCtx = testCtx;
273 std::unique_ptr<StreamBuilder> builder = createBuilder(testCtx->getPerformanceMode());
274 if (!builder) return false;
275 // Do not set channel count, because AAudio doesn't perform channel count conversion
276 // in the exclusive mode.
277 builder->setSampleRate(testCtx->getSamplingRateHz());
278 mStream = builder->makeStream();
279 if (!mStream) return false;
280 mStream->setBufferFrameCount(testCtx->getFrameCount());
281 mWriteCallback = writeClb;
282 mErrorCallback = errorClb;
283 return mStream->start();
284 }
285
shutdown()286 void Player::shutdown() {
287 if (mStream) {
288 mStream->stop();
289 mStream.reset();
290 }
291 }
292
aaudioDataCallback(AAudioStream *,void * userData,void * audioData,int32_t numFrames)293 aaudio_data_callback_result_t Player::aaudioDataCallback(AAudioStream* /*stream*/,
294 void *userData,
295 void *audioData,
296 int32_t numFrames) {
297 ATRACE_CALL();
298 Player *self = static_cast<Player*>(userData);
299 AudioBufferView<sample_t> outputWave = self->mWriteCallback(numFrames);
300 if (outputWave.getFrameCount() > static_cast<size_t>(numFrames)) {
301 ALOGW("Output wave has more frames than callback allows: %lld > %d",
302 (long long)outputWave.getFrameCount(), numFrames);
303 }
304
305 copyAudioBufferViewData(outputWave,
306 AudioBufferView<sample_t>(static_cast<sample_t*>(audioData),
307 numFrames, self->mStream->getChannelCount()));
308
309 return AAUDIO_CALLBACK_RESULT_CONTINUE;
310 }
311
aaudioErrorCallback(AAudioStream *,void * userData,aaudio_result_t error)312 void Player::aaudioErrorCallback(AAudioStream* /*stream*/,
313 void *userData,
314 aaudio_result_t error) {
315 Player *self = static_cast<Player*>(userData);
316 self->mErrorCallback(error);
317 }
318
319
320 class Recorder {
321 public:
Recorder()322 Recorder() {}
323 Recorder(const Recorder&) = delete;
324 Recorder& operator=(const Recorder&) = delete;
~Recorder()325 ~Recorder() { shutdown(); }
326
327 bool probeDefaults(
328 PerformanceMode performanceMode, int *samplingRate, int *recorderBufferFrameCount);
329 bool init(const TestContext *testCtx);
330 bool drain();
331 ssize_t read(AudioBufferView<sample_t> buffer);
332 void shutdown();
333
334 private:
335 // The input stream buffer size in milliseconds. For the input, buffer
336 // size affects latency less than for the output stream (at least in MMAP mode),
337 // because the app normally drains the input buffer and should keep it low.
338 // Using twice the size of the Player buffer as an educated guess.
339 static constexpr int MINIMUM_STREAM_BUFFER_SIZE_MS = 8;
340
341 std::unique_ptr<StreamBuilder> createBuilder(PerformanceMode performanceMode);
342
343 const TestContext *mTestCtx;
344 std::unique_ptr<Stream> mStream;
345 std::unique_ptr<AudioBuffer<sample_t>> mConversionBuffer;
346 };
347
createBuilder(PerformanceMode performanceMode)348 std::unique_ptr<StreamBuilder> Recorder::createBuilder(PerformanceMode performanceMode) {
349 std::unique_ptr<StreamBuilder> builder = makeStreamBuilder();
350 if (builder) {
351 builder->setDirection(AAUDIO_DIRECTION_INPUT);
352 builder->setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
353 builder->setPerformanceMode(getAAudioPerfMode(performanceMode));
354 static_assert(sizeof(sample_t) == sizeof(int16_t), "sample format must be int16");
355 builder->setFormat(AAUDIO_FORMAT_PCM_I16);
356 }
357 return builder;
358 }
359
probeDefaults(PerformanceMode performanceMode,int * samplingRate,int * recorderBufferFrameCount)360 bool Recorder::probeDefaults(
361 PerformanceMode performanceMode, int *samplingRate, int *recorderBufferFrameCount) {
362 std::unique_ptr<StreamBuilder> builder = createBuilder(performanceMode);
363 if (!builder) return false;
364 mStream = builder->makeStream();
365 if (!mStream) return false;
366 *samplingRate = mStream->getSamplingRateHz();
367 *recorderBufferFrameCount = calculateBufferSizeInFrames(
368 mStream->getFramesPerBurst(), MINIMUM_STREAM_BUFFER_SIZE_MS, *samplingRate);
369 return true;
370 }
371
init(const TestContext * testCtx)372 bool Recorder::init(const TestContext *testCtx) {
373 mTestCtx = testCtx;
374 std::unique_ptr<StreamBuilder> builder = createBuilder(testCtx->getPerformanceMode());
375 if (!builder) return false;
376 builder->setChannelCount(testCtx->getChannelCount());
377 builder->setSampleRate(testCtx->getSamplingRateHz());
378 mStream = builder->makeStream();
379 if (!mStream) return false;
380 if (mStream->getChannelCount() != mTestCtx->getChannelCount()) {
381 mConversionBuffer.reset(new AudioBuffer<sample_t>(
382 mTestCtx->getFrameCount(), mStream->getChannelCount()));
383 }
384 mStream->setBufferFrameCount(testCtx->getFrameCount());
385 return mStream->start();
386 }
387
drain()388 bool Recorder::drain() {
389 ATRACE_CALL();
390 AudioBuffer<sample_t> drainBuffer(mStream->getFramesPerBurst(), mStream->getChannelCount());
391 ssize_t framesRead;
392 do {
393 framesRead = mStream->read(drainBuffer);
394 if (framesRead < 0) return false;
395 } while (framesRead > 0);
396 return true;
397 }
398
read(AudioBufferView<sample_t> buffer)399 ssize_t Recorder::read(AudioBufferView<sample_t> buffer) {
400 if (!mConversionBuffer) {
401 return mStream->read(buffer);
402 } else {
403 ssize_t result = mStream->read(mConversionBuffer->getView(0, buffer.getFrameCount()));
404 if (result <= 0) return result;
405
406 size_t framesRead = result;
407 copyAudioBufferViewData(mConversionBuffer->getView(0, framesRead), buffer);
408 return framesRead;
409 }
410 }
411
shutdown()412 void Recorder::shutdown() {
413 if (mStream) {
414 mStream->stop();
415 mStream.reset();
416 }
417 }
418
419
420 } // namespace
421
422 struct SoundSystemAAudio::Impl {
ImplSoundSystemAAudio::Impl423 Impl() : lastError(AAUDIO_OK) {}
424 Impl(const Impl&) = delete;
425 Impl& operator=(const Impl&) = delete;
426
errorCallbackSoundSystemAAudio::Impl427 void errorCallback(aaudio_result_t error) {
428 lastError = error;
429 ALOGE("Error callback received %s (%d)",
430 AAudioLoader::getInstance()->convertResultToText(error), error);
431 }
432
433 Player player;
434 Recorder recorder;
435 std::atomic<aaudio_result_t> lastError;
436 };
437
SoundSystemAAudio()438 SoundSystemAAudio::SoundSystemAAudio()
439 : mTestCtx(nullptr), mImpl(new Impl()) {
440 }
441
SoundSystemAAudio(const TestContext * testCtx)442 SoundSystemAAudio::SoundSystemAAudio(const TestContext *testCtx)
443 : mTestCtx(testCtx), mImpl(new Impl()) {
444 }
445
~SoundSystemAAudio()446 SoundSystemAAudio::~SoundSystemAAudio() {
447 shutdown();
448 }
449
probeDefaultSettings(PerformanceMode performanceMode,int * samplingRate,int * playerBufferFrameCount,int * recorderBufferFrameCount)450 bool SoundSystemAAudio::probeDefaultSettings(PerformanceMode performanceMode, int *samplingRate,
451 int *playerBufferFrameCount, int *recorderBufferFrameCount) {
452 return (AAudioLoader::getInstance()->open() == 0)
453 && mImpl->recorder.probeDefaults(
454 performanceMode, samplingRate, recorderBufferFrameCount)
455 && mImpl->player.probeDefaults(performanceMode, samplingRate, playerBufferFrameCount);
456 }
457
init(WriteCallback callback)458 bool SoundSystemAAudio::init(WriteCallback callback) {
459 if (!mTestCtx) {
460 ALOGF("Attempting to use SoundSystemAAudio probing instance for testing!");
461 }
462 return (AAudioLoader::getInstance()->open() == 0)
463 && mImpl->recorder.init(mTestCtx)
464 && mImpl->player.init(
465 mTestCtx,
466 callback,
467 std::bind(&Impl::errorCallback, mImpl.get(), std::placeholders::_1));
468 }
469
drainInput()470 bool SoundSystemAAudio::drainInput() {
471 if (mImpl->lastError != AAUDIO_OK) return false;
472 return mImpl->recorder.drain();
473 }
474
readAudio(AudioBufferView<sample_t> buffer)475 ssize_t SoundSystemAAudio::readAudio(AudioBufferView<sample_t> buffer) {
476 if (mImpl->lastError != AAUDIO_OK) return -1;
477 return mImpl->recorder.read(buffer);
478 }
479
shutdown()480 void SoundSystemAAudio::shutdown() {
481 mImpl->player.shutdown();
482 mImpl->recorder.shutdown();
483 AAudioLoader::getInstance()->close();
484 }
485