• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright  2019 Google LLC
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  *     https://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 "DuplexEngine.h"
18 #include "effects/Effects.h"
19 
DuplexEngine()20 DuplexEngine::DuplexEngine() {
21     beginStreams();
22 }
23 
beginStreams()24 void DuplexEngine::beginStreams() {
25     // This ordering is extremely important
26     openInStream();
27     if (inStream->getFormat() == oboe::AudioFormat::Float) {
28         functionList.emplace<FunctionList<float *>>();
29         createCallback<float_t>();
30     } else if (inStream->getFormat() == oboe::AudioFormat::I16) {
31         createCallback<int16_t>();
32     } else {
33         stopStreams();
34     }
35     SAMPLE_RATE = inStream->getSampleRate();
36     openOutStream();
37 
38     oboe::Result result = startStreams();
39     if (result != oboe::Result::OK) stopStreams();
40 }
41 
42 template<class numeric>
createCallback()43 void DuplexEngine::createCallback() {
44     mCallback = std::make_unique<DuplexCallback<numeric>>(
45             *inStream, [&functionStack = this->functionList](numeric *beg, numeric *end) {
46                 std::get<FunctionList<numeric *>>(functionStack)(beg, end);
47             },
48             inStream->getBufferCapacityInFrames(),
49             std::bind(&DuplexEngine::beginStreams, this));
50 }
51 
52 
defaultBuilder()53 oboe::AudioStreamBuilder DuplexEngine::defaultBuilder() {
54     return *oboe::AudioStreamBuilder()
55             .setPerformanceMode(oboe::PerformanceMode::LowLatency)
56             ->setSharingMode(oboe::SharingMode::Exclusive);
57 }
58 
openInStream()59 void DuplexEngine::openInStream() {
60     defaultBuilder().setDirection(oboe::Direction::Input)
61             ->setFormat(oboe::AudioFormat::Float) // For now
62             ->setChannelCount(1) // Mono in for effects processing
63             ->openManagedStream(inStream);
64 }
65 
openOutStream()66 void DuplexEngine::openOutStream() {
67     defaultBuilder().setCallback(mCallback.get())
68             ->setSampleRate(inStream->getSampleRate())
69             ->setFormat(inStream->getFormat())
70             ->setChannelCount(2) // Stereo out
71             ->openManagedStream(outStream);
72 }
73 
startStreams()74 oboe::Result DuplexEngine::startStreams() {
75     oboe::Result result = outStream->requestStart();
76     int64_t timeoutNanos = 500 * 1000000; // arbitrary 1/2 second
77     auto currentState = outStream->getState();
78     auto nextState = oboe::StreamState::Unknown;
79     while (result == oboe::Result::OK && currentState != oboe::StreamState::Started) {
80         result = outStream->waitForStateChange(currentState, &nextState, timeoutNanos);
81         currentState = nextState;
82     }
83     if (result != oboe::Result::OK) return result;
84     return inStream->requestStart();
85 }
86 
stopStreams()87 oboe::Result DuplexEngine::stopStreams() {
88     oboe::Result outputResult = inStream->requestStop();
89     oboe::Result inputResult = outStream->requestStop();
90     if (outputResult != oboe::Result::OK) return outputResult;
91     return inputResult;
92 }
93 
94