diff options
Diffstat (limited to 'externals/oboe/src/common/DataConversionFlowGraph.cpp')
| -rw-r--r-- | externals/oboe/src/common/DataConversionFlowGraph.cpp | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/externals/oboe/src/common/DataConversionFlowGraph.cpp b/externals/oboe/src/common/DataConversionFlowGraph.cpp deleted file mode 100644 index 0bb51ae2eb..0000000000 --- a/externals/oboe/src/common/DataConversionFlowGraph.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * 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 - * - * http://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 <memory> - -#include "OboeDebug.h" -#include "DataConversionFlowGraph.h" -#include "SourceFloatCaller.h" -#include "SourceI16Caller.h" -#include "SourceI24Caller.h" -#include "SourceI32Caller.h" - -#include <flowgraph/MonoToMultiConverter.h> -#include <flowgraph/MultiToMonoConverter.h> -#include <flowgraph/RampLinear.h> -#include <flowgraph/SinkFloat.h> -#include <flowgraph/SinkI16.h> -#include <flowgraph/SinkI24.h> -#include <flowgraph/SinkI32.h> -#include <flowgraph/SourceFloat.h> -#include <flowgraph/SourceI16.h> -#include <flowgraph/SourceI24.h> -#include <flowgraph/SourceI32.h> -#include <flowgraph/SampleRateConverter.h> - -using namespace oboe; -using namespace flowgraph; -using namespace resampler; - -void DataConversionFlowGraph::setSource(const void *buffer, int32_t numFrames) { - mSource->setData(buffer, numFrames); -} - -static MultiChannelResampler::Quality convertOboeSRQualityToMCR(SampleRateConversionQuality quality) { - switch (quality) { - case SampleRateConversionQuality::Fastest: - return MultiChannelResampler::Quality::Fastest; - case SampleRateConversionQuality::Low: - return MultiChannelResampler::Quality::Low; - default: - case SampleRateConversionQuality::Medium: - return MultiChannelResampler::Quality::Medium; - case SampleRateConversionQuality::High: - return MultiChannelResampler::Quality::High; - case SampleRateConversionQuality::Best: - return MultiChannelResampler::Quality::Best; - } -} - -// Chain together multiple processors. -// Callback Output -// Use SourceCaller that calls original app callback from the flowgraph. -// The child callback from FilteredAudioStream read()s from the flowgraph. -// Callback Input -// Child callback from FilteredAudioStream writes()s to the flowgraph. -// The output of the flowgraph goes through a BlockWriter to the app callback. -// Blocking Write -// Write buffer is set on an AudioSource. -// Data is pulled through the graph and written to the child stream. -// Blocking Read -// Reads in a loop from the flowgraph Sink to fill the read buffer. -// A SourceCaller then does a blocking read from the child Stream. -// -Result DataConversionFlowGraph::configure(AudioStream *sourceStream, AudioStream *sinkStream) { - - FlowGraphPortFloatOutput *lastOutput = nullptr; - - bool isOutput = sourceStream->getDirection() == Direction::Output; - bool isInput = !isOutput; - mFilterStream = isOutput ? sourceStream : sinkStream; - - AudioFormat sourceFormat = sourceStream->getFormat(); - int32_t sourceChannelCount = sourceStream->getChannelCount(); - int32_t sourceSampleRate = sourceStream->getSampleRate(); - int32_t sourceFramesPerCallback = sourceStream->getFramesPerDataCallback(); - - AudioFormat sinkFormat = sinkStream->getFormat(); - int32_t sinkChannelCount = sinkStream->getChannelCount(); - int32_t sinkSampleRate = sinkStream->getSampleRate(); - int32_t sinkFramesPerCallback = sinkStream->getFramesPerDataCallback(); - - LOGI("%s() flowgraph converts channels: %d to %d, format: %s to %s" - ", rate: %d to %d, cbsize: %d to %d, qual = %s", - __func__, - sourceChannelCount, sinkChannelCount, - oboe::convertToText(sourceFormat), oboe::convertToText(sinkFormat), - sourceSampleRate, sinkSampleRate, - sourceFramesPerCallback, sinkFramesPerCallback, - oboe::convertToText(sourceStream->getSampleRateConversionQuality())); - - // Source - // IF OUTPUT and using a callback then call back to the app using a SourceCaller. - // OR IF INPUT and NOT using a callback then read from the child stream using a SourceCaller. - bool isDataCallbackSpecified = sourceStream->isDataCallbackSpecified(); - if ((isDataCallbackSpecified && isOutput) - || (!isDataCallbackSpecified && isInput)) { - int32_t actualSourceFramesPerCallback = (sourceFramesPerCallback == kUnspecified) - ? sourceStream->getFramesPerBurst() - : sourceFramesPerCallback; - switch (sourceFormat) { - case AudioFormat::Float: - mSourceCaller = std::make_unique<SourceFloatCaller>(sourceChannelCount, - actualSourceFramesPerCallback); - break; - case AudioFormat::I16: - mSourceCaller = std::make_unique<SourceI16Caller>(sourceChannelCount, - actualSourceFramesPerCallback); - break; - case AudioFormat::I24: - mSourceCaller = std::make_unique<SourceI24Caller>(sourceChannelCount, - actualSourceFramesPerCallback); - break; - case AudioFormat::I32: - mSourceCaller = std::make_unique<SourceI32Caller>(sourceChannelCount, - actualSourceFramesPerCallback); - break; - default: - LOGE("%s() Unsupported source caller format = %d", __func__, static_cast<int>(sourceFormat)); - return Result::ErrorIllegalArgument; - } - mSourceCaller->setStream(sourceStream); - lastOutput = &mSourceCaller->output; - } else { - // IF OUTPUT and NOT using a callback then write to the child stream using a BlockWriter. - // OR IF INPUT and using a callback then write to the app using a BlockWriter. - switch (sourceFormat) { - case AudioFormat::Float: - mSource = std::make_unique<SourceFloat>(sourceChannelCount); - break; - case AudioFormat::I16: - mSource = std::make_unique<SourceI16>(sourceChannelCount); - break; - case AudioFormat::I24: - mSource = std::make_unique<SourceI24>(sourceChannelCount); - break; - case AudioFormat::I32: - mSource = std::make_unique<SourceI32>(sourceChannelCount); - break; - default: - LOGE("%s() Unsupported source format = %d", __func__, static_cast<int>(sourceFormat)); - return Result::ErrorIllegalArgument; - } - if (isInput) { - int32_t actualSinkFramesPerCallback = (sinkFramesPerCallback == kUnspecified) - ? sinkStream->getFramesPerBurst() - : sinkFramesPerCallback; - // The BlockWriter is after the Sink so use the SinkStream size. - mBlockWriter.open(actualSinkFramesPerCallback * sinkStream->getBytesPerFrame()); - mAppBuffer = std::make_unique<uint8_t[]>( - kDefaultBufferSize * sinkStream->getBytesPerFrame()); - } - lastOutput = &mSource->output; - } - - // If we are going to reduce the number of channels then do it before the - // sample rate converter. - if (sourceChannelCount > sinkChannelCount) { - if (sinkChannelCount == 1) { - mMultiToMonoConverter = std::make_unique<MultiToMonoConverter>(sourceChannelCount); - lastOutput->connect(&mMultiToMonoConverter->input); - lastOutput = &mMultiToMonoConverter->output; - } else { - mChannelCountConverter = std::make_unique<ChannelCountConverter>( - sourceChannelCount, - sinkChannelCount); - lastOutput->connect(&mChannelCountConverter->input); - lastOutput = &mChannelCountConverter->output; - } - } - - // Sample Rate conversion - if (sourceSampleRate != sinkSampleRate) { - // Create a resampler to do the math. - mResampler.reset(MultiChannelResampler::make(lastOutput->getSamplesPerFrame(), - sourceSampleRate, - sinkSampleRate, - convertOboeSRQualityToMCR( - sourceStream->getSampleRateConversionQuality()))); - // Make a flowgraph node that uses the resampler. - mRateConverter = std::make_unique<SampleRateConverter>(lastOutput->getSamplesPerFrame(), - *mResampler.get()); - lastOutput->connect(&mRateConverter->input); - lastOutput = &mRateConverter->output; - } - - // Expand the number of channels if required. - if (sourceChannelCount < sinkChannelCount) { - if (sourceChannelCount == 1) { - mMonoToMultiConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount); - lastOutput->connect(&mMonoToMultiConverter->input); - lastOutput = &mMonoToMultiConverter->output; - } else { - mChannelCountConverter = std::make_unique<ChannelCountConverter>( - sourceChannelCount, - sinkChannelCount); - lastOutput->connect(&mChannelCountConverter->input); - lastOutput = &mChannelCountConverter->output; - } - } - - // Sink - switch (sinkFormat) { - case AudioFormat::Float: - mSink = std::make_unique<SinkFloat>(sinkChannelCount); - break; - case AudioFormat::I16: - mSink = std::make_unique<SinkI16>(sinkChannelCount); - break; - case AudioFormat::I24: - mSink = std::make_unique<SinkI24>(sinkChannelCount); - break; - case AudioFormat::I32: - mSink = std::make_unique<SinkI32>(sinkChannelCount); - break; - default: - LOGE("%s() Unsupported sink format = %d", __func__, static_cast<int>(sinkFormat)); - return Result::ErrorIllegalArgument;; - } - lastOutput->connect(&mSink->input); - - return Result::OK; -} - -int32_t DataConversionFlowGraph::read(void *buffer, int32_t numFrames, int64_t timeoutNanos) { - if (mSourceCaller) { - mSourceCaller->setTimeoutNanos(timeoutNanos); - } - int32_t numRead = mSink->read(buffer, numFrames); - return numRead; -} - -// This is similar to pushing data through the flowgraph. -int32_t DataConversionFlowGraph::write(void *inputBuffer, int32_t numFrames) { - // Put the data from the input at the head of the flowgraph. - mSource->setData(inputBuffer, numFrames); - while (true) { - // Pull and read some data in app format into a small buffer. - int32_t framesRead = mSink->read(mAppBuffer.get(), flowgraph::kDefaultBufferSize); - if (framesRead <= 0) break; - // Write to a block adapter, which will call the destination whenever it has enough data. - int32_t bytesRead = mBlockWriter.write(mAppBuffer.get(), - framesRead * mFilterStream->getBytesPerFrame()); - if (bytesRead < 0) return bytesRead; // TODO review - } - return numFrames; -} - -int32_t DataConversionFlowGraph::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) { - int32_t numFrames = numBytes / mFilterStream->getBytesPerFrame(); - mCallbackResult = mFilterStream->getDataCallback()->onAudioReady(mFilterStream, buffer, numFrames); - // TODO handle STOP from callback, process data remaining in the block adapter - return numBytes; -} |
