• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 
18 #include <memory>
19 #include "MegaDroneEngine.h"
20 
21 /**
22  * Main audio engine for the MegaDrone sample. It is responsible for:
23  *
24  * - Creating the callback object which will be supplied when constructing the audio stream
25  * - Setting the CPU core IDs to which the callback thread should bind to
26  * - Creating the playback stream, including setting the callback object
27  * - Creating `Synth` which will render the audio inside the callback
28  * - Starting the playback stream
29  * - Restarting the playback stream when `restart()` is called by the callback object
30  *
31  * @param cpuIds
32  */
MegaDroneEngine(std::vector<int> cpuIds)33 MegaDroneEngine::MegaDroneEngine(std::vector<int> cpuIds) {
34     createCallback(cpuIds);
35 }
36 
~MegaDroneEngine()37 MegaDroneEngine::~MegaDroneEngine() {
38     if (mStream) {
39         LOGE("MegaDroneEngine destructor was called without calling stop()."
40              "Please call stop() to ensure stream resources are not leaked.");
41         stop();
42     }
43 }
44 
tap(bool isDown)45 void MegaDroneEngine::tap(bool isDown) {
46     mAudioSource->tap(isDown);
47 }
48 
restart()49 void MegaDroneEngine::restart() {
50     stop();
51     start();
52 }
53 // Create the playback stream
createPlaybackStream()54 oboe::Result MegaDroneEngine::createPlaybackStream() {
55     oboe::AudioStreamBuilder builder;
56     return builder.setSharingMode(oboe::SharingMode::Exclusive)
57             ->setPerformanceMode(oboe::PerformanceMode::LowLatency)
58             ->setFormat(oboe::AudioFormat::Float)
59             ->setDataCallback(mDataCallback.get())
60             ->setErrorCallback(mErrorCallback.get())
61             ->openStream(mStream);
62 }
63 
64 // Create the callback and set its thread affinity to the supplied CPU core IDs
createCallback(std::vector<int> cpuIds)65 void MegaDroneEngine::createCallback(std::vector<int> cpuIds){
66 
67     mDataCallback = std::make_unique<DefaultDataCallback>();
68 
69     // Create the error callback, we supply ourselves as the parent so that we can restart the stream
70     // when it's disconnected
71     mErrorCallback = std::make_unique<DefaultErrorCallback>(*this);
72 
73     // Bind the audio callback to specific CPU cores as this can help avoid underruns caused by
74     // core migrations
75     mDataCallback->setCpuIds(cpuIds);
76     mDataCallback->setThreadAffinityEnabled(true);
77 }
78 
start()79 bool MegaDroneEngine::start(){
80     auto result = createPlaybackStream();
81     if (result == Result::OK){
82         // Create our synthesizer audio source using the properties of the stream
83         mAudioSource = std::make_shared<Synth>(mStream->getSampleRate(), mStream->getChannelCount());
84         mDataCallback->reset();
85         mDataCallback->setSource(std::dynamic_pointer_cast<IRenderableAudio>(mAudioSource));
86         mStream->start();
87         return true;
88     } else {
89         LOGE("Failed to create the playback stream. Error: %s", convertToText(result));
90         return false;
91     }
92 }
93 
stop()94 bool MegaDroneEngine::stop() {
95     if(mStream && mStream->getState() != oboe::StreamState::Closed) {
96         mStream->stop();
97         mStream->close();
98     }
99     mStream.reset();
100     return true;
101 }
102 
103