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