diff options
| author | swurl <swurl@swurl.xyz> | 2025-05-31 02:33:02 -0400 |
|---|---|---|
| committer | swurl <swurl@swurl.xyz> | 2025-05-31 02:33:02 -0400 |
| commit | 6c655321e6b04b8648802e296bb5ca11d290ae68 (patch) | |
| tree | 5c906511e4a2910ce8b806bb9d763b524c28619e /externals/oboe/tests/testFullDuplexStream.cpp | |
| parent | c0cceff365f754f8859f4c9a0362ebdba7ea388b (diff) | |
Move dead submodules in-tree
Signed-off-by: swurl <swurl@swurl.xyz>
Diffstat (limited to 'externals/oboe/tests/testFullDuplexStream.cpp')
| -rw-r--r-- | externals/oboe/tests/testFullDuplexStream.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/externals/oboe/tests/testFullDuplexStream.cpp b/externals/oboe/tests/testFullDuplexStream.cpp new file mode 100644 index 0000000000..b8b9688eb7 --- /dev/null +++ b/externals/oboe/tests/testFullDuplexStream.cpp @@ -0,0 +1,206 @@ +/* + * Copyright 2023 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 <thread> + +#include <gtest/gtest.h> + +#include <oboe/Oboe.h> + +using namespace oboe; + +static constexpr int kTimeToSleepMicros = 5 * 1000 * 1000; // 5 s + +using TestFullDuplexStreamParams = std::tuple<AudioApi, PerformanceMode, AudioApi, PerformanceMode>; + +class TestFullDuplexStream : public ::testing::Test, + public ::testing::WithParamInterface<TestFullDuplexStreamParams>, + public FullDuplexStream { +public: + DataCallbackResult onBothStreamsReady( + const void *inputData, + int numInputFrames, + void *outputData, + int numOutputFrames) override { + mCallbackCount++; + if (numInputFrames == numOutputFrames) { + mGoodCallbackCount++; + } + return DataCallbackResult::Continue; + } + +protected: + + void openStream(AudioApi inputAudioApi, PerformanceMode inputPerfMode, + AudioApi outputAudioApi, PerformanceMode outputPerfMode) { + mOutputBuilder.setDirection(Direction::Output); + if (mOutputBuilder.isAAudioRecommended()) { + mOutputBuilder.setAudioApi(outputAudioApi); + } + mOutputBuilder.setPerformanceMode(outputPerfMode); + mOutputBuilder.setChannelCount(1); + mOutputBuilder.setFormat(AudioFormat::Float); + mOutputBuilder.setDataCallback(this); + + Result r = mOutputBuilder.openStream(mOutputStream); + ASSERT_EQ(r, Result::OK) << "Failed to open output stream " << convertToText(r); + + mInputBuilder.setDirection(Direction::Input); + if (mInputBuilder.isAAudioRecommended()) { + mInputBuilder.setAudioApi(inputAudioApi); + } + mInputBuilder.setPerformanceMode(inputPerfMode); + mInputBuilder.setChannelCount(1); + mInputBuilder.setFormat(AudioFormat::Float); + mInputBuilder.setBufferCapacityInFrames(mOutputStream->getBufferCapacityInFrames() * 2); + mInputBuilder.setSampleRate(mOutputStream->getSampleRate()); + + r = mInputBuilder.openStream(mInputStream); + ASSERT_EQ(r, Result::OK) << "Failed to open input stream " << convertToText(r); + + setSharedInputStream(mInputStream); + setSharedOutputStream(mOutputStream); + } + + void startStream() { + Result r = start(); + ASSERT_EQ(r, Result::OK) << "Failed to start streams " << convertToText(r); + } + + void stopStream() { + Result r = stop(); + ASSERT_EQ(r, Result::OK) << "Failed to stop streams " << convertToText(r); + } + + void closeStream() { + Result r = mOutputStream->close(); + ASSERT_EQ(r, Result::OK) << "Failed to close output stream " << convertToText(r); + r = mInputStream->close(); + ASSERT_EQ(r, Result::OK) << "Failed to close input stream " << convertToText(r); + } + + void checkXRuns() { + // Expect few xRuns with the use of full duplex stream + EXPECT_LT(mInputStream->getXRunCount().value(), 10); + EXPECT_LT(mOutputStream->getXRunCount().value(), 10); + } + + void checkInputAndOutputBufferSizesMatch() { + // Expect the large majority of callbacks to have the same sized input and output + EXPECT_GE(mGoodCallbackCount, mCallbackCount * 4 / 5); + } + + AudioStreamBuilder mInputBuilder; + AudioStreamBuilder mOutputBuilder; + std::shared_ptr<AudioStream> mInputStream; + std::shared_ptr<AudioStream> mOutputStream; + std::atomic<int32_t> mCallbackCount{0}; + std::atomic<int32_t> mGoodCallbackCount{0}; +}; + +TEST_P(TestFullDuplexStream, VerifyFullDuplexStream) { + const AudioApi inputAudioApi = std::get<0>(GetParam()); + const PerformanceMode inputPerformanceMode = std::get<1>(GetParam()); + const AudioApi outputAudioApi = std::get<2>(GetParam()); + const PerformanceMode outputPerformanceMode = std::get<3>(GetParam()); + + openStream(inputAudioApi, inputPerformanceMode, outputAudioApi, outputPerformanceMode); + startStream(); + usleep(kTimeToSleepMicros); + checkXRuns(); + checkInputAndOutputBufferSizesMatch(); + stopStream(); + closeStream(); +} + +INSTANTIATE_TEST_SUITE_P( + TestFullDuplexStreamTest, + TestFullDuplexStream, + ::testing::Values( + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::LowLatency, + AudioApi::AAudio, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::LowLatency, + AudioApi::AAudio, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::LowLatency, + AudioApi::AAudio, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::LowLatency, + AudioApi::OpenSLES, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::LowLatency, + AudioApi::OpenSLES, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::LowLatency, + AudioApi::OpenSLES, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::None, + AudioApi::AAudio, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::None, + AudioApi::AAudio, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::None, + AudioApi::AAudio, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::None, + AudioApi::OpenSLES, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::None, + AudioApi::OpenSLES, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::None, + AudioApi::OpenSLES, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::PowerSaving, + AudioApi::AAudio, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::PowerSaving, + AudioApi::AAudio, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::PowerSaving, + AudioApi::AAudio, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::PowerSaving, + AudioApi::OpenSLES, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::PowerSaving, + AudioApi::OpenSLES, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::AAudio, PerformanceMode::PowerSaving, + AudioApi::OpenSLES, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::LowLatency, + AudioApi::AAudio, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::LowLatency, + AudioApi::AAudio, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::LowLatency, + AudioApi::AAudio, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::LowLatency, + AudioApi::OpenSLES, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::LowLatency, + AudioApi::OpenSLES, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::LowLatency, + AudioApi::OpenSLES, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::None, + AudioApi::AAudio, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::None, + AudioApi::AAudio, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::None, + AudioApi::AAudio, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::None, + AudioApi::OpenSLES, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::None, + AudioApi::OpenSLES, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::None, + AudioApi::OpenSLES, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::PowerSaving, + AudioApi::AAudio, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::PowerSaving, + AudioApi::AAudio, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::PowerSaving, + AudioApi::AAudio, PerformanceMode::PowerSaving}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::PowerSaving, + AudioApi::OpenSLES, PerformanceMode::LowLatency}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::PowerSaving, + AudioApi::OpenSLES, PerformanceMode::None}), + TestFullDuplexStreamParams({AudioApi::OpenSLES, PerformanceMode::PowerSaving, + AudioApi::OpenSLES, PerformanceMode::PowerSaving}) + ) +); |
