blob: 123d52c33a17d4077b4ec4567cf507a71ca0774b [file] [log] [blame]
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DuplexEngine.h"
#include "effects/Effects.h"
DuplexEngine::DuplexEngine() {
beginStreams();
}
void DuplexEngine::beginStreams() {
// This ordering is extremely important
openInStream();
if (inStream->getFormat() == oboe::AudioFormat::Float) {
functionList.emplace<FunctionList<float *>>();
createCallback<float_t>();
} else if (inStream->getFormat() == oboe::AudioFormat::I16) {
createCallback<int16_t>();
} else {
stopStreams();
}
SAMPLE_RATE = inStream->getSampleRate();
openOutStream();
oboe::Result result = startStreams();
if (result != oboe::Result::OK) stopStreams();
}
template<class numeric>
void DuplexEngine::createCallback() {
mCallback = std::make_unique<DuplexCallback<numeric>>(
*inStream, [&functionStack = this->functionList](numeric *beg, numeric *end) {
std::get<FunctionList<numeric *>>(functionStack)(beg, end);
},
inStream->getBufferCapacityInFrames(),
std::bind(&DuplexEngine::beginStreams, this));
}
oboe::AudioStreamBuilder DuplexEngine::defaultBuilder() {
return *oboe::AudioStreamBuilder()
.setPerformanceMode(oboe::PerformanceMode::LowLatency)
->setSharingMode(oboe::SharingMode::Exclusive);
}
void DuplexEngine::openInStream() {
defaultBuilder().setDirection(oboe::Direction::Input)
->setFormat(oboe::AudioFormat::Float) // For now
->setChannelCount(1) // Mono in for effects processing
->openManagedStream(inStream);
}
void DuplexEngine::openOutStream() {
defaultBuilder().setCallback(mCallback.get())
->setSampleRate(inStream->getSampleRate())
->setFormat(inStream->getFormat())
->setChannelCount(2) // Stereo out
->openManagedStream(outStream);
}
oboe::Result DuplexEngine::startStreams() {
oboe::Result result = outStream->requestStart();
int64_t timeoutNanos = 500 * 1000000; // arbitrary 1/2 second
auto currentState = outStream->getState();
auto nextState = oboe::StreamState::Unknown;
while (result == oboe::Result::OK && currentState != oboe::StreamState::Started) {
result = outStream->waitForStateChange(currentState, &nextState, timeoutNanos);
currentState = nextState;
}
if (result != oboe::Result::OK) return result;
return inStream->requestStart();
}
oboe::Result DuplexEngine::stopStreams() {
oboe::Result outputResult = inStream->requestStop();
oboe::Result inputResult = outStream->requestStop();
if (outputResult != oboe::Result::OK) return outputResult;
return inputResult;
}