Move dead submodules in-tree

Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
swurl 2025-05-31 02:33:02 -04:00
parent c0cceff365
commit 6c655321e6
No known key found for this signature in database
GPG key ID: A5A7629F109C8FD1
4081 changed files with 1185566 additions and 45 deletions

View file

@ -0,0 +1,60 @@
#
# Copyright 2017 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.
#
cmake_minimum_required(VERSION 3.4.1)
### INCLUDE OBOE LIBRARY ###
# Set the path to the Oboe library directory
set (OBOE_DIR ../../../../../)
# Add the Oboe library as a subproject. Since Oboe is an out-of-tree source library we must also
# specify a binary directory
add_subdirectory(${OBOE_DIR} ./oboe-bin)
# Include the Oboe headers and shared sample code
include_directories(${OBOE_DIR}/include ${OBOE_DIR}/samples/shared)
# Debug utilities
set (DEBUG_UTILS_PATH "${OBOE_DIR}/samples/debug-utils")
set (DEBUG_UTILS_SOURCES ${DEBUG_UTILS_PATH}/trace.cpp)
include_directories(${DEBUG_UTILS_PATH})
### END OBOE INCLUDE SECTION ###
# App specific sources
set (APP_SOURCES
jni_bridge.cpp
HelloOboeEngine.cpp
SoundGenerator.cpp
LatencyTuningCallback.cpp
)
# Build the libhello-oboe library
add_library(hello-oboe SHARED
${DEBUG_UTILS_SOURCES}
${APP_SOURCES}
)
# Specify the libraries needed for hello-oboe
target_link_libraries(hello-oboe android log oboe)
target_link_options(hello-oboe PRIVATE "-Wl,-z,max-page-size=16384")
# Enable optimization flags: if having problems with source level debugging,
# disable -Ofast ( and debug ), re-enable after done debugging.
target_compile_options(hello-oboe PRIVATE -Wall -Werror "$<$<CONFIG:RELEASE>:-Ofast>")

View file

@ -0,0 +1,175 @@
/**
* Copyright 2017 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 <inttypes.h>
#include <memory>
#include <Oscillator.h>
#include "HelloOboeEngine.h"
#include "SoundGenerator.h"
/**
* Main audio engine for the HelloOboe sample. It is responsible for:
*
* - Creating a callback object which is supplied when constructing the audio stream, and will be
* called when the stream starts
* - Restarting the stream when user-controllable properties (Audio API, channel count etc) are
* changed, and when the stream is disconnected (e.g. when headphones are attached)
* - Calculating the audio latency of the stream
*
*/
HelloOboeEngine::HelloOboeEngine()
: mLatencyCallback(std::make_shared<LatencyTuningCallback>()),
mErrorCallback(std::make_shared<DefaultErrorCallback>(*this)) {
}
double HelloOboeEngine::getCurrentOutputLatencyMillis() {
if (!mIsLatencyDetectionSupported) return -1.0;
std::lock_guard<std::mutex> lock(mLock);
if (!mStream) return -1.0;
oboe::ResultWithValue<double> latencyResult = mStream->calculateLatencyMillis();
if (latencyResult) {
return latencyResult.value();
} else {
LOGE("Error calculating latency: %s", oboe::convertToText(latencyResult.error()));
return -1.0;
}
}
void HelloOboeEngine::setBufferSizeInBursts(int32_t numBursts) {
std::lock_guard<std::mutex> lock(mLock);
if (!mStream) return;
mLatencyCallback->setBufferTuneEnabled(numBursts == kBufferSizeAutomatic);
auto result = mStream->setBufferSizeInFrames(
numBursts * mStream->getFramesPerBurst());
if (result) {
LOGD("Buffer size successfully changed to %d", result.value());
} else {
LOGW("Buffer size could not be changed, %d", result.error());
}
}
bool HelloOboeEngine::isLatencyDetectionSupported() {
return mIsLatencyDetectionSupported;
}
bool HelloOboeEngine::isAAudioRecommended() {
return oboe::AudioStreamBuilder::isAAudioRecommended();
}
void HelloOboeEngine::tap(bool isDown) {
if (mAudioSource) {
mAudioSource->tap(isDown);
}
}
oboe::Result HelloOboeEngine::openPlaybackStream() {
oboe::AudioStreamBuilder builder;
oboe::Result result = builder.setSharingMode(oboe::SharingMode::Exclusive)
->setPerformanceMode(oboe::PerformanceMode::LowLatency)
->setFormat(oboe::AudioFormat::Float)
->setFormatConversionAllowed(true)
->setDataCallback(mLatencyCallback)
->setErrorCallback(mErrorCallback)
->setAudioApi(mAudioApi)
->setChannelCount(mChannelCount)
->setDeviceId(mDeviceId)
->openStream(mStream);
if (result == oboe::Result::OK) {
mChannelCount = mStream->getChannelCount();
}
return result;
}
void HelloOboeEngine::restart() {
// The stream will have already been closed by the error callback.
mLatencyCallback->reset();
start();
}
oboe::Result HelloOboeEngine::start(oboe::AudioApi audioApi, int deviceId, int channelCount) {
mAudioApi = audioApi;
mDeviceId = deviceId;
mChannelCount = channelCount;
return start();
}
oboe::Result HelloOboeEngine::start() {
std::lock_guard<std::mutex> lock(mLock);
oboe::Result result = oboe::Result::OK;
// It is possible for a stream's device to become disconnected during the open or between
// the Open and the Start.
// So if it fails to start, close the old stream and try again.
int tryCount = 0;
do {
if (tryCount > 0) {
usleep(20 * 1000); // Sleep between tries to give the system time to settle.
}
mIsLatencyDetectionSupported = false;
result = openPlaybackStream();
if (result == oboe::Result::OK) {
mAudioSource = std::make_shared<SoundGenerator>(mStream->getSampleRate(),
mStream->getChannelCount());
mLatencyCallback->setSource(
std::dynamic_pointer_cast<IRenderableAudio>(mAudioSource));
LOGD("Stream opened: AudioAPI = %d, channelCount = %d, deviceID = %d",
mStream->getAudioApi(),
mStream->getChannelCount(),
mStream->getDeviceId());
result = mStream->requestStart();
if (result != oboe::Result::OK) {
LOGE("Error starting playback stream. Error: %s", oboe::convertToText(result));
mStream->close();
mStream.reset();
} else {
mIsLatencyDetectionSupported = (mStream->getTimestamp((CLOCK_MONOTONIC)) !=
oboe::Result::ErrorUnimplemented);
}
} else {
LOGE("Error creating playback stream. Error: %s", oboe::convertToText(result));
}
} while (result != oboe::Result::OK && tryCount++ < 3);
return result;
}
oboe::Result HelloOboeEngine::stop() {
oboe::Result result = oboe::Result::OK;
// Stop, close and delete in case not already closed.
std::lock_guard<std::mutex> lock(mLock);
if (mStream) {
result = mStream->stop();
mStream->close();
mStream.reset();
}
return result;
}
oboe::Result HelloOboeEngine::reopenStream() {
if (mStream) {
stop();
return start();
} else {
return oboe::Result::OK;
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright 2017 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.
*/
#ifndef OBOE_HELLO_OBOE_ENGINE_H
#define OBOE_HELLO_OBOE_ENGINE_H
#include <oboe/Oboe.h>
#include "SoundGenerator.h"
#include "LatencyTuningCallback.h"
#include "IRestartable.h"
#include "DefaultErrorCallback.h"
constexpr int32_t kBufferSizeAutomatic = 0;
class HelloOboeEngine : public IRestartable {
public:
HelloOboeEngine();
virtual ~HelloOboeEngine() = default;
void tap(bool isDown);
/**
* Open and start a stream.
* @param deviceId the audio device id, can be obtained through an {@link AudioDeviceInfo} object
* using Java/JNI.
* @return error or OK
*/
oboe::Result start(oboe::AudioApi audioApi, int deviceId, int channelCount);
/* Start using current settings. */
oboe::Result start();
/**
* Stop and close the stream.
*/
oboe::Result stop();
// From IRestartable
void restart() override;
void setBufferSizeInBursts(int32_t numBursts);
/**
* Calculate the current latency between writing a frame to the output stream and
* the same frame being presented to the audio hardware.
*
* Here's how the calculation works:
*
* 1) Get the time a particular frame was presented to the audio hardware
* @see AudioStream::getTimestamp
* 2) From this extrapolate the time which the *next* audio frame written to the stream
* will be presented
* 3) Assume that the next audio frame is written at the current time
* 4) currentLatency = nextFramePresentationTime - nextFrameWriteTime
*
* @return Output Latency in Milliseconds
*/
double getCurrentOutputLatencyMillis();
bool isLatencyDetectionSupported();
bool isAAudioRecommended();
private:
oboe::Result reopenStream();
oboe::Result openPlaybackStream();
std::shared_ptr<oboe::AudioStream> mStream;
std::shared_ptr<LatencyTuningCallback> mLatencyCallback;
std::shared_ptr<DefaultErrorCallback> mErrorCallback;
std::shared_ptr<SoundGenerator> mAudioSource;
bool mIsLatencyDetectionSupported = false;
int32_t mDeviceId = oboe::Unspecified;
int32_t mChannelCount = oboe::Unspecified;
oboe::AudioApi mAudioApi = oboe::AudioApi::Unspecified;
std::mutex mLock;
};
#endif //OBOE_HELLO_OBOE_ENGINE_H

View file

@ -0,0 +1,45 @@
/**
* Copyright 2017 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 "LatencyTuningCallback.h"
oboe::DataCallbackResult LatencyTuningCallback::onAudioReady(
oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
if (oboeStream != mStream) {
mStream = oboeStream;
mLatencyTuner = std::make_unique<oboe::LatencyTuner>(*oboeStream);
}
if (mBufferTuneEnabled
&& mLatencyTuner
&& oboeStream->getAudioApi() == oboe::AudioApi::AAudio) {
mLatencyTuner->tune();
}
auto underrunCountResult = oboeStream->getXRunCount();
int bufferSize = oboeStream->getBufferSizeInFrames();
/**
* The following output can be seen by running a systrace. Tracing is preferable to logging
* inside the callback since tracing does not block.
*
* See https://developer.android.com/studio/profile/systrace-commandline.html
*/
if (Trace::isEnabled()) Trace::beginSection("numFrames %d, Underruns %d, buffer size %d",
numFrames, underrunCountResult.value(), bufferSize);
auto result = DefaultDataCallback::onAudioReady(oboeStream, audioData, numFrames);
if (Trace::isEnabled()) Trace::endSection();
return result;
}

View file

@ -0,0 +1,67 @@
/**
* Copyright 2017 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.
*/
#ifndef SAMPLES_LATENCY_TUNING_CALLBACK_H
#define SAMPLES_LATENCY_TUNING_CALLBACK_H
#include <oboe/Oboe.h>
#include <oboe/LatencyTuner.h>
#include <TappableAudioSource.h>
#include <DefaultDataCallback.h>
#include <trace.h>
/**
* This callback object extends the functionality of `DefaultDataCallback` by automatically
* tuning the latency of the audio stream. @see onAudioReady for more details on this.
*
* It also demonstrates how to use tracing functions for logging inside the audio callback without
* blocking.
*/
class LatencyTuningCallback: public DefaultDataCallback {
public:
LatencyTuningCallback() : DefaultDataCallback() {
// Initialize the trace functions, this enables you to output trace statements without
// blocking. See https://developer.android.com/studio/profile/systrace-commandline.html
Trace::initialize();
}
/**
* Every time the playback stream requires data this method will be called.
*
* @param audioStream the audio stream which is requesting data, this is the mPlayStream object
* @param audioData an empty buffer into which we can write our audio data
* @param numFrames the number of audio frames which are required
* @return Either oboe::DataCallbackResult::Continue if the stream should continue requesting data
* or oboe::DataCallbackResult::Stop if the stream should stop.
*/
oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override;
void setBufferTuneEnabled(bool enabled) {mBufferTuneEnabled = enabled;}
void useStream(std::shared_ptr<oboe::AudioStream> stream);
private:
bool mBufferTuneEnabled = true;
// This will be used to automatically tune the buffer size of the stream, obtaining optimal latency
std::unique_ptr<oboe::LatencyTuner> mLatencyTuner;
oboe::AudioStream *mStream = nullptr;
};
#endif //SAMPLES_LATENCY_TUNING_CALLBACK_H

View file

@ -0,0 +1,51 @@
/*
* Copyright 2018 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 "SoundGenerator.h"
SoundGenerator::SoundGenerator(int32_t sampleRate, int32_t channelCount) :
TappableAudioSource(sampleRate, channelCount)
, mOscillators(std::make_unique<Oscillator[]>(channelCount)){
double frequency = 440.0;
constexpr double interval = 110.0;
constexpr float amplitude = 1.0;
// Set up the oscillators
for (int i = 0; i < mChannelCount; ++i) {
mOscillators[i].setFrequency(frequency);
mOscillators[i].setSampleRate(mSampleRate);
mOscillators[i].setAmplitude(amplitude);
frequency += interval;
}
}
void SoundGenerator::renderAudio(float *audioData, int32_t numFrames) {
// Render each oscillator into its own channel
std::fill_n(mBuffer.get(), kSharedBufferSize, 0);
for (int i = 0; i < mChannelCount; ++i) {
mOscillators[i].renderAudio(mBuffer.get(), numFrames);
for (int j = 0; j < numFrames; ++j) {
audioData[(j * mChannelCount) + i] = mBuffer[j];
}
}
}
void SoundGenerator::tap(bool isOn) {
for (int i = 0; i < mChannelCount; ++i) {
mOscillators[i].setWaveOn(isOn);
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright 2018 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.
*/
#ifndef SAMPLES_SOUNDGENERATOR_H
#define SAMPLES_SOUNDGENERATOR_H
#include <Oscillator.h>
#include <TappableAudioSource.h>
/**
* Generates a fixed frequency tone for each channel.
* Implements RenderableTap (sound source with toggle) which is required for AudioEngines.
*/
class SoundGenerator : public TappableAudioSource {
static constexpr size_t kSharedBufferSize = 1024;
public:
/**
* Create a new SoundGenerator object.
*
* @param sampleRate - The output sample rate.
* @param maxFrames - The maximum number of audio frames which will be rendered, this is used to
* calculate this object's internal buffer size.
* @param channelCount - The number of channels in the output, one tone will be created for each
* channel, the output will be interlaced.
*
*/
SoundGenerator(int32_t sampleRate, int32_t channelCount);
~SoundGenerator() = default;
SoundGenerator(SoundGenerator&& other) = default;
SoundGenerator& operator= (SoundGenerator&& other) = default;
// Switch the tones on
void tap(bool isOn) override;
void renderAudio(float *audioData, int32_t numFrames) override;
private:
std::unique_ptr<Oscillator[]> mOscillators;
std::unique_ptr<float[]> mBuffer = std::make_unique<float[]>(kSharedBufferSize);
};
#endif //SAMPLES_SOUNDGENERATOR_H

View file

@ -0,0 +1,90 @@
/*
* Copyright 2017 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 <jni.h>
#include <oboe/Oboe.h>
#include "HelloOboeEngine.h"
#include "logging_macros.h"
extern "C" {
/* We only need one HelloOboeEngine and it is needed for the entire time.
* So just allocate one statically. */
static HelloOboeEngine sEngine;
JNIEXPORT jint JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_startEngine(
JNIEnv *env,
jclass,
int audioApi, int deviceId, int channelCount) {
return static_cast<jint>(sEngine.start((oboe::AudioApi)audioApi, deviceId, channelCount));
}
JNIEXPORT jint JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_stopEngine(
JNIEnv *env,
jclass) {
return static_cast<jint>(sEngine.stop());
}
JNIEXPORT void JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_setToneOn(
JNIEnv *env,
jclass,
jboolean isToneOn) {
sEngine.tap(isToneOn);
}
JNIEXPORT void JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_setBufferSizeInBursts(
JNIEnv *env,
jclass,
jint bufferSizeInBursts) {
sEngine.setBufferSizeInBursts(bufferSizeInBursts);
}
JNIEXPORT jdouble JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_getCurrentOutputLatencyMillis(
JNIEnv *env,
jclass) {
return static_cast<jdouble>(sEngine.getCurrentOutputLatencyMillis());
}
JNIEXPORT jboolean JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_isLatencyDetectionSupported(
JNIEnv *env,
jclass) {
return (sEngine.isLatencyDetectionSupported() ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_isAAudioRecommended(
JNIEnv *env,
jclass) {
return (sEngine.isAAudioRecommended() ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT void JNICALL
Java_com_google_oboe_samples_hellooboe_PlaybackEngine_setDefaultStreamValues(
JNIEnv *env,
jclass,
jint sampleRate,
jint framesPerBurst) {
oboe::DefaultStreamValues::SampleRate = (int32_t) sampleRate;
oboe::DefaultStreamValues::FramesPerBurst = (int32_t) framesPerBurst;
}
} // extern "C"