aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/tests/testFullDuplexStream.cpp
diff options
context:
space:
mode:
authorswurl <swurl@swurl.xyz>2025-05-31 02:33:02 -0400
committerswurl <swurl@swurl.xyz>2025-05-31 02:33:02 -0400
commit6c655321e6b04b8648802e296bb5ca11d290ae68 (patch)
tree5c906511e4a2910ce8b806bb9d763b524c28619e /externals/oboe/tests/testFullDuplexStream.cpp
parentc0cceff365f754f8859f4c9a0362ebdba7ea388b (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.cpp206
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})
+ )
+);