aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/apps/OboeTester/app/src/main/cpp/TestColdStartLatency.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/oboe/apps/OboeTester/app/src/main/cpp/TestColdStartLatency.cpp')
-rw-r--r--externals/oboe/apps/OboeTester/app/src/main/cpp/TestColdStartLatency.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/externals/oboe/apps/OboeTester/app/src/main/cpp/TestColdStartLatency.cpp b/externals/oboe/apps/OboeTester/app/src/main/cpp/TestColdStartLatency.cpp
new file mode 100644
index 0000000000..9b4f25ca14
--- /dev/null
+++ b/externals/oboe/apps/OboeTester/app/src/main/cpp/TestColdStartLatency.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <stdlib.h>
+#include <aaudio/AAudioExtensions.h>
+
+#include "common/OboeDebug.h"
+#include "oboe/AudioClock.h"
+#include "TestColdStartLatency.h"
+#include "OboeTools.h"
+
+using namespace oboe;
+
+int32_t TestColdStartLatency::open(bool useInput, bool useLowLatency, bool useMmap, bool
+ useExclusive) {
+
+ mDataCallback = std::make_shared<MyDataCallback>();
+
+ // Enable MMAP if needed
+ bool wasMMapEnabled = AAudioExtensions::getInstance().isMMapEnabled();
+ AAudioExtensions::getInstance().setMMapEnabled(useMmap);
+
+ int64_t beginOpenNanos = AudioClock::getNanoseconds();
+
+ AudioStreamBuilder builder;
+ Result result = builder.setFormat(AudioFormat::Float)
+ ->setPerformanceMode(useLowLatency ? PerformanceMode::LowLatency :
+ PerformanceMode::None)
+ ->setDirection(useInput ? Direction::Input : Direction::Output)
+ ->setChannelCount(kChannelCount)
+ ->setDataCallback(mDataCallback)
+ ->setSharingMode(useExclusive ? SharingMode::Exclusive : SharingMode::Shared)
+ ->openStream(mStream);
+
+ int64_t endOpenNanos = AudioClock::getNanoseconds();
+ int64_t actualDurationNanos = endOpenNanos - beginOpenNanos;
+ mOpenTimeMicros = actualDurationNanos / NANOS_PER_MICROSECOND;
+
+ // Revert MMAP back to its previous state
+ AAudioExtensions::getInstance().setMMapEnabled(wasMMapEnabled);
+
+ mDeviceId = mStream->getDeviceId();
+
+ return (int32_t) result;
+}
+
+int32_t TestColdStartLatency::start() {
+ mBeginStartNanos = AudioClock::getNanoseconds();
+ Result result = mStream->requestStart();
+ int64_t endStartNanos = AudioClock::getNanoseconds();
+ int64_t actualDurationNanos = endStartNanos - mBeginStartNanos;
+ mStartTimeMicros = actualDurationNanos / NANOS_PER_MICROSECOND;
+ return (int32_t) result;
+}
+
+int32_t TestColdStartLatency::close() {
+ Result result1 = mStream->requestStop();
+ Result result2 = mStream->close();
+ return (int32_t)((result1 != Result::OK) ? result1 : result2);
+}
+
+int32_t TestColdStartLatency::getColdStartTimeMicros() {
+ int64_t position;
+ int64_t timestampNanos;
+ if (mStream->getDirection() == Direction::Output) {
+ auto result = mStream->getTimestamp(CLOCK_MONOTONIC);
+ if (!result) {
+ return -1; // ERROR
+ }
+ auto frameTimestamp = result.value();
+ // Calculate the time that frame[0] would have been played by the speaker.
+ position = frameTimestamp.position;
+ timestampNanos = frameTimestamp.timestamp;
+ } else {
+ position = mStream->getFramesRead();
+ timestampNanos = AudioClock::getNanoseconds();
+ }
+ double sampleRate = (double) mStream->getSampleRate();
+
+ int64_t elapsedNanos = NANOS_PER_SECOND * (position / sampleRate);
+ int64_t timeOfFrameZero = timestampNanos - elapsedNanos;
+ int64_t coldStartLatencyNanos = timeOfFrameZero - mBeginStartNanos;
+ return coldStartLatencyNanos / NANOS_PER_MICROSECOND;
+}
+
+// Callback that sleeps then touches the audio buffer.
+DataCallbackResult TestColdStartLatency::MyDataCallback::onAudioReady(
+ AudioStream *audioStream,
+ void *audioData,
+ int32_t numFrames) {
+ float *floatData = (float *) audioData;
+ const int numSamples = numFrames * kChannelCount;
+ if (audioStream->getDirection() == Direction::Output) {
+ // Fill mono buffer with a sine wave.
+ for (int i = 0; i < numSamples; i++) {
+ *floatData++ = sinf(mPhase) * 0.2f;
+ if ((i % kChannelCount) == (kChannelCount - 1)) {
+ mPhase += kPhaseIncrement;
+ // Wrap the phase around in a circle.
+ if (mPhase >= M_PI) mPhase -= 2 * M_PI;
+ }
+ }
+ }
+ return DataCallbackResult::Continue;
+}