mirror of
https://github.com/love2d/love-android.git
synced 2026-08-12 08:31:04 +02:00
Revert "Manually extract Oboe AAR for now."
This reverts commit 190938943f.
This commit is contained in:
@@ -101,4 +101,5 @@ dependencies {
|
||||
implementation 'androidx.navigation:navigation-ui:2.4.2'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation 'com.google.oboe:oboe:1.6.1'
|
||||
}
|
||||
|
||||
@@ -2,13 +2,6 @@ cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
project(love-android LANGUAGES C CXX)
|
||||
|
||||
# Oboe
|
||||
set(Oboe_DIR "${CMAKE_CURRENT_SOURCE_DIR}/oboe")
|
||||
|
||||
# Set LOVE
|
||||
set(MEGA_LOVE "${CMAKE_CURRENT_SOURCE_DIR}/love")
|
||||
|
||||
# Finally, load megasource that will handle everything.
|
||||
add_subdirectory(megasource)
|
||||
|
||||
# TODO: Third-party libraries.
|
||||
|
||||
BIN
Binary file not shown.
@@ -1,567 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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_STREAM_H_
|
||||
#define OBOE_STREAM_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <mutex>
|
||||
#include "oboe/Definitions.h"
|
||||
#include "oboe/ResultWithValue.h"
|
||||
#include "oboe/AudioStreamBuilder.h"
|
||||
#include "oboe/AudioStreamBase.h"
|
||||
|
||||
/** WARNING - UNDER CONSTRUCTION - THIS API WILL CHANGE. */
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* The default number of nanoseconds to wait for when performing state change operations on the
|
||||
* stream, such as `start` and `stop`.
|
||||
*
|
||||
* @see oboe::AudioStream::start
|
||||
*/
|
||||
constexpr int64_t kDefaultTimeoutNanos = (2000 * kNanosPerMillisecond);
|
||||
|
||||
/**
|
||||
* Base class for Oboe C++ audio stream.
|
||||
*/
|
||||
class AudioStream : public AudioStreamBase {
|
||||
friend class AudioStreamBuilder; // allow access to setWeakThis() and lockWeakThis()
|
||||
public:
|
||||
|
||||
AudioStream() {}
|
||||
|
||||
/**
|
||||
* Construct an `AudioStream` using the given `AudioStreamBuilder`
|
||||
*
|
||||
* @param builder containing all the stream's attributes
|
||||
*/
|
||||
explicit AudioStream(const AudioStreamBuilder &builder);
|
||||
|
||||
virtual ~AudioStream() = default;
|
||||
|
||||
/**
|
||||
* Open a stream based on the current settings.
|
||||
*
|
||||
* Note that we do not recommend re-opening a stream that has been closed.
|
||||
* TODO Should we prevent re-opening?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
virtual Result open() {
|
||||
return Result::OK; // Called by subclasses. Might do more in the future.
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream and deallocate any resources from the open() call.
|
||||
*/
|
||||
virtual Result close();
|
||||
|
||||
/**
|
||||
* Start the stream. This will block until the stream has been started, an error occurs
|
||||
* or `timeoutNanoseconds` has been reached.
|
||||
*/
|
||||
virtual Result start(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
|
||||
|
||||
/**
|
||||
* Pause the stream. This will block until the stream has been paused, an error occurs
|
||||
* or `timeoutNanoseconds` has been reached.
|
||||
*/
|
||||
virtual Result pause(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
|
||||
|
||||
/**
|
||||
* Flush the stream. This will block until the stream has been flushed, an error occurs
|
||||
* or `timeoutNanoseconds` has been reached.
|
||||
*/
|
||||
virtual Result flush(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
|
||||
|
||||
/**
|
||||
* Stop the stream. This will block until the stream has been stopped, an error occurs
|
||||
* or `timeoutNanoseconds` has been reached.
|
||||
*/
|
||||
virtual Result stop(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
|
||||
|
||||
/* Asynchronous requests.
|
||||
* Use waitForStateChange() if you need to wait for completion.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling
|
||||
* `start(0)`.
|
||||
*/
|
||||
virtual Result requestStart() = 0;
|
||||
|
||||
/**
|
||||
* Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling
|
||||
* `pause(0)`.
|
||||
*/
|
||||
virtual Result requestPause() = 0;
|
||||
|
||||
/**
|
||||
* Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling
|
||||
* `flush(0)`.
|
||||
*/
|
||||
virtual Result requestFlush() = 0;
|
||||
|
||||
/**
|
||||
* Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling
|
||||
* `stop(0)`.
|
||||
*/
|
||||
virtual Result requestStop() = 0;
|
||||
|
||||
/**
|
||||
* Query the current state, eg. StreamState::Pausing
|
||||
*
|
||||
* @return state or a negative error.
|
||||
*/
|
||||
virtual StreamState getState() = 0;
|
||||
|
||||
/**
|
||||
* Wait until the stream's current state no longer matches the input state.
|
||||
* The input state is passed to avoid race conditions caused by the state
|
||||
* changing between calls.
|
||||
*
|
||||
* Note that generally applications do not need to call this. It is considered
|
||||
* an advanced technique and is mostly used for testing.
|
||||
*
|
||||
* <pre><code>
|
||||
* int64_t timeoutNanos = 500 * kNanosPerMillisecond; // arbitrary 1/2 second
|
||||
* StreamState currentState = stream->getState();
|
||||
* StreamState nextState = StreamState::Unknown;
|
||||
* while (result == Result::OK && currentState != StreamState::Paused) {
|
||||
* result = stream->waitForStateChange(
|
||||
* currentState, &nextState, timeoutNanos);
|
||||
* currentState = nextState;
|
||||
* }
|
||||
* </code></pre>
|
||||
*
|
||||
* If the state does not change within the timeout period then it will
|
||||
* return ErrorTimeout. This is true even if timeoutNanoseconds is zero.
|
||||
*
|
||||
* @param inputState The state we want to change away from.
|
||||
* @param nextState Pointer to a variable that will be set to the new state.
|
||||
* @param timeoutNanoseconds The maximum time to wait in nanoseconds.
|
||||
* @return Result::OK or a Result::Error.
|
||||
*/
|
||||
virtual Result waitForStateChange(StreamState inputState,
|
||||
StreamState *nextState,
|
||||
int64_t timeoutNanoseconds) = 0;
|
||||
|
||||
/**
|
||||
* This can be used to adjust the latency of the buffer by changing
|
||||
* the threshold where blocking will occur.
|
||||
* By combining this with getXRunCount(), the latency can be tuned
|
||||
* at run-time for each device.
|
||||
*
|
||||
* This cannot be set higher than getBufferCapacity().
|
||||
*
|
||||
* @param requestedFrames requested number of frames that can be filled without blocking
|
||||
* @return the resulting buffer size in frames (obtained using value()) or an error (obtained
|
||||
* using error())
|
||||
*/
|
||||
virtual ResultWithValue<int32_t> setBufferSizeInFrames(int32_t /* requestedFrames */) {
|
||||
return Result::ErrorUnimplemented;
|
||||
}
|
||||
|
||||
/**
|
||||
* An XRun is an Underrun or an Overrun.
|
||||
* During playing, an underrun will occur if the stream is not written in time
|
||||
* and the system runs out of valid data.
|
||||
* During recording, an overrun will occur if the stream is not read in time
|
||||
* and there is no place to put the incoming data so it is discarded.
|
||||
*
|
||||
* An underrun or overrun can cause an audible "pop" or "glitch".
|
||||
*
|
||||
* @return a result which is either Result::OK with the xRun count as the value, or a
|
||||
* Result::Error* code
|
||||
*/
|
||||
virtual ResultWithValue<int32_t> getXRunCount() {
|
||||
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if XRun counts are supported on the stream
|
||||
*/
|
||||
virtual bool isXRunCountSupported() const = 0;
|
||||
|
||||
/**
|
||||
* Query the number of frames that are read or written by the endpoint at one time.
|
||||
*
|
||||
* @return burst size
|
||||
*/
|
||||
int32_t getFramesPerBurst() const {
|
||||
return mFramesPerBurst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes in each audio frame. This is calculated using the channel count
|
||||
* and the sample format. For example, a 2 channel floating point stream will have
|
||||
* 2 * 4 = 8 bytes per frame.
|
||||
*
|
||||
* @return number of bytes in each audio frame.
|
||||
*/
|
||||
int32_t getBytesPerFrame() const { return mChannelCount * getBytesPerSample(); }
|
||||
|
||||
/**
|
||||
* Get the number of bytes per sample. This is calculated using the sample format. For example,
|
||||
* a stream using 16-bit integer samples will have 2 bytes per sample.
|
||||
*
|
||||
* @return the number of bytes per sample.
|
||||
*/
|
||||
int32_t getBytesPerSample() const;
|
||||
|
||||
/**
|
||||
* The number of audio frames written into the stream.
|
||||
* This monotonic counter will never get reset.
|
||||
*
|
||||
* @return the number of frames written so far
|
||||
*/
|
||||
virtual int64_t getFramesWritten();
|
||||
|
||||
/**
|
||||
* The number of audio frames read from the stream.
|
||||
* This monotonic counter will never get reset.
|
||||
*
|
||||
* @return the number of frames read so far
|
||||
*/
|
||||
virtual int64_t getFramesRead();
|
||||
|
||||
/**
|
||||
* Calculate the latency of a stream based on getTimestamp().
|
||||
*
|
||||
* Output latency is the time it takes for a given frame to travel from the
|
||||
* app to some type of digital-to-analog converter. If the DAC is external, for example
|
||||
* in a USB interface or a TV connected by HDMI, then there may be additional latency
|
||||
* that the Android device is unaware of.
|
||||
*
|
||||
* Input latency is the time it takes to a given frame to travel from an analog-to-digital
|
||||
* converter (ADC) to the app.
|
||||
*
|
||||
* Note that the latency of an OUTPUT stream will increase abruptly when you write data to it
|
||||
* and then decrease slowly over time as the data is consumed.
|
||||
*
|
||||
* The latency of an INPUT stream will decrease abruptly when you read data from it
|
||||
* and then increase slowly over time as more data arrives.
|
||||
*
|
||||
* The latency of an OUTPUT stream is generally higher than the INPUT latency
|
||||
* because an app generally tries to keep the OUTPUT buffer full and the INPUT buffer empty.
|
||||
*
|
||||
* @return a ResultWithValue which has a result of Result::OK and a value containing the latency
|
||||
* in milliseconds, or a result of Result::Error*.
|
||||
*/
|
||||
virtual ResultWithValue<double> calculateLatencyMillis() {
|
||||
return ResultWithValue<double>(Result::ErrorUnimplemented);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the estimated time that the frame at `framePosition` entered or left the audio processing
|
||||
* pipeline.
|
||||
*
|
||||
* This can be used to coordinate events and interactions with the external environment, and to
|
||||
* estimate the latency of an audio stream. An example of usage can be found in the hello-oboe
|
||||
* sample (search for "calculateCurrentOutputLatencyMillis").
|
||||
*
|
||||
* The time is based on the implementation's best effort, using whatever knowledge is available
|
||||
* to the system, but cannot account for any delay unknown to the implementation.
|
||||
*
|
||||
* @deprecated since 1.0, use AudioStream::getTimestamp(clockid_t clockId) instead, which
|
||||
* returns ResultWithValue
|
||||
* @param clockId the type of clock to use e.g. CLOCK_MONOTONIC
|
||||
* @param framePosition the frame number to query
|
||||
* @param timeNanoseconds an output parameter which will contain the presentation timestamp
|
||||
*/
|
||||
virtual Result getTimestamp(clockid_t /* clockId */,
|
||||
int64_t* /* framePosition */,
|
||||
int64_t* /* timeNanoseconds */) {
|
||||
return Result::ErrorUnimplemented;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the estimated time that the frame at `framePosition` entered or left the audio processing
|
||||
* pipeline.
|
||||
*
|
||||
* This can be used to coordinate events and interactions with the external environment, and to
|
||||
* estimate the latency of an audio stream. An example of usage can be found in the hello-oboe
|
||||
* sample (search for "calculateCurrentOutputLatencyMillis").
|
||||
*
|
||||
* The time is based on the implementation's best effort, using whatever knowledge is available
|
||||
* to the system, but cannot account for any delay unknown to the implementation.
|
||||
*
|
||||
* @param clockId the type of clock to use e.g. CLOCK_MONOTONIC
|
||||
* @return a FrameTimestamp containing the position and time at which a particular audio frame
|
||||
* entered or left the audio processing pipeline, or an error if the operation failed.
|
||||
*/
|
||||
virtual ResultWithValue<FrameTimestamp> getTimestamp(clockid_t /* clockId */);
|
||||
|
||||
// ============== I/O ===========================
|
||||
/**
|
||||
* Write data from the supplied buffer into the stream. This method will block until the write
|
||||
* is complete or it runs out of time.
|
||||
*
|
||||
* If `timeoutNanoseconds` is zero then this call will not wait.
|
||||
*
|
||||
* @param buffer The address of the first sample.
|
||||
* @param numFrames Number of frames to write. Only complete frames will be written.
|
||||
* @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
|
||||
* @return a ResultWithValue which has a result of Result::OK and a value containing the number
|
||||
* of frames actually written, or result of Result::Error*.
|
||||
*/
|
||||
virtual ResultWithValue<int32_t> write(const void* /* buffer */,
|
||||
int32_t /* numFrames */,
|
||||
int64_t /* timeoutNanoseconds */ ) {
|
||||
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data into the supplied buffer from the stream. This method will block until the read
|
||||
* is complete or it runs out of time.
|
||||
*
|
||||
* If `timeoutNanoseconds` is zero then this call will not wait.
|
||||
*
|
||||
* @param buffer The address of the first sample.
|
||||
* @param numFrames Number of frames to read. Only complete frames will be read.
|
||||
* @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
|
||||
* @return a ResultWithValue which has a result of Result::OK and a value containing the number
|
||||
* of frames actually read, or result of Result::Error*.
|
||||
*/
|
||||
virtual ResultWithValue<int32_t> read(void* /* buffer */,
|
||||
int32_t /* numFrames */,
|
||||
int64_t /* timeoutNanoseconds */) {
|
||||
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying audio API which the stream uses.
|
||||
*
|
||||
* @return the API that this stream uses.
|
||||
*/
|
||||
virtual AudioApi getAudioApi() const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the underlying audio API is AAudio.
|
||||
*
|
||||
* @return true if this stream is implemented using the AAudio API.
|
||||
*/
|
||||
bool usesAAudio() const {
|
||||
return getAudioApi() == AudioApi::AAudio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for debugging. Do not use in production.
|
||||
* If you need to call this method something is wrong.
|
||||
* If you think you need it for production then please let us know
|
||||
* so we can modify Oboe so that you don't need this.
|
||||
*
|
||||
* @return nullptr or a pointer to a stream from the system API
|
||||
*/
|
||||
virtual void *getUnderlyingStream() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update mFramesWritten.
|
||||
* For internal use only.
|
||||
*/
|
||||
virtual void updateFramesWritten() = 0;
|
||||
|
||||
/**
|
||||
* Update mFramesRead.
|
||||
* For internal use only.
|
||||
*/
|
||||
virtual void updateFramesRead() = 0;
|
||||
|
||||
/*
|
||||
* Swap old callback for new callback.
|
||||
* This not atomic.
|
||||
* This should only be used internally.
|
||||
* @param dataCallback
|
||||
* @return previous dataCallback
|
||||
*/
|
||||
AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) {
|
||||
AudioStreamDataCallback *previousCallback = mDataCallback;
|
||||
mDataCallback = dataCallback;
|
||||
return previousCallback;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap old callback for new callback.
|
||||
* This not atomic.
|
||||
* This should only be used internally.
|
||||
* @param errorCallback
|
||||
* @return previous errorCallback
|
||||
*/
|
||||
AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) {
|
||||
AudioStreamErrorCallback *previousCallback = mErrorCallback;
|
||||
mErrorCallback = errorCallback;
|
||||
return previousCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of frames of data currently in the buffer
|
||||
*/
|
||||
ResultWithValue<int32_t> getAvailableFrames();
|
||||
|
||||
/**
|
||||
* Wait until the stream has a minimum amount of data available in its buffer.
|
||||
* This can be used with an EXCLUSIVE MMAP input stream to avoid reading data too close to
|
||||
* the DSP write position, which may cause glitches.
|
||||
*
|
||||
* @param numFrames minimum frames available
|
||||
* @param timeoutNanoseconds
|
||||
* @return number of frames available, ErrorTimeout
|
||||
*/
|
||||
ResultWithValue<int32_t> waitForAvailableFrames(int32_t numFrames,
|
||||
int64_t timeoutNanoseconds);
|
||||
|
||||
/**
|
||||
* @return last result passed from an error callback
|
||||
*/
|
||||
virtual oboe::Result getLastErrorCallbackResult() const {
|
||||
return mErrorCallbackResult;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* This is used to detect more than one error callback from a stream.
|
||||
* These were bugs in some versions of Android that caused multiple error callbacks.
|
||||
* Internal bug b/63087953
|
||||
*
|
||||
* Calling this sets an atomic<bool> true and returns the previous value.
|
||||
*
|
||||
* @return false on first call, true on subsequent calls
|
||||
*/
|
||||
bool wasErrorCallbackCalled() {
|
||||
return mErrorCallbackCalled.exchange(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a transition from one state to another.
|
||||
* @return OK if the endingState was observed, or ErrorUnexpectedState
|
||||
* if any state that was not the startingState or endingState was observed
|
||||
* or ErrorTimeout.
|
||||
*/
|
||||
virtual Result waitForStateTransition(StreamState startingState,
|
||||
StreamState endingState,
|
||||
int64_t timeoutNanoseconds);
|
||||
|
||||
/**
|
||||
* Override this to provide a default for when the application did not specify a callback.
|
||||
*
|
||||
* @param audioData
|
||||
* @param numFrames
|
||||
* @return result
|
||||
*/
|
||||
virtual DataCallbackResult onDefaultCallback(void* /* audioData */, int /* numFrames */) {
|
||||
return DataCallbackResult::Stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to provide your own behaviour for the audio callback
|
||||
*
|
||||
* @param audioData container array which audio frames will be written into or read from
|
||||
* @param numFrames number of frames which were read/written
|
||||
* @return the result of the callback: stop or continue
|
||||
*
|
||||
*/
|
||||
DataCallbackResult fireDataCallback(void *audioData, int numFrames);
|
||||
|
||||
/**
|
||||
* @return true if callbacks may be called
|
||||
*/
|
||||
bool isDataCallbackEnabled() {
|
||||
return mDataCallbackEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be set false internally to prevent callbacks
|
||||
* after DataCallbackResult::Stop has been returned.
|
||||
*/
|
||||
void setDataCallbackEnabled(bool enabled) {
|
||||
mDataCallbackEnabled = enabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a weak_ptr to this stream from the shared_ptr so that we can
|
||||
* later use a shared_ptr in the error callback.
|
||||
*/
|
||||
void setWeakThis(std::shared_ptr<oboe::AudioStream> &sharedStream) {
|
||||
mWeakThis = sharedStream;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a shared_ptr that will prevent this stream from being deleted.
|
||||
*/
|
||||
std::shared_ptr<oboe::AudioStream> lockWeakThis() {
|
||||
return mWeakThis.lock();
|
||||
}
|
||||
|
||||
std::weak_ptr<AudioStream> mWeakThis; // weak pointer to this object
|
||||
|
||||
/**
|
||||
* Number of frames which have been written into the stream
|
||||
*
|
||||
* This is signed integer to match the counters in AAudio.
|
||||
* At audio rates, the counter will overflow in about six million years.
|
||||
*/
|
||||
std::atomic<int64_t> mFramesWritten{};
|
||||
|
||||
/**
|
||||
* Number of frames which have been read from the stream.
|
||||
*
|
||||
* This is signed integer to match the counters in AAudio.
|
||||
* At audio rates, the counter will overflow in about six million years.
|
||||
*/
|
||||
std::atomic<int64_t> mFramesRead{};
|
||||
|
||||
std::mutex mLock; // for synchronizing start/stop/close
|
||||
|
||||
oboe::Result mErrorCallbackResult = oboe::Result::OK;
|
||||
|
||||
/**
|
||||
* Number of frames which will be copied to/from the audio device in a single read/write
|
||||
* operation
|
||||
*/
|
||||
int32_t mFramesPerBurst = kUnspecified;
|
||||
|
||||
private:
|
||||
|
||||
// Log the scheduler if it changes.
|
||||
void checkScheduler();
|
||||
int mPreviousScheduler = -1;
|
||||
|
||||
std::atomic<bool> mDataCallbackEnabled{false};
|
||||
std::atomic<bool> mErrorCallbackCalled{false};
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct is a stateless functor which closes an AudioStream prior to its deletion.
|
||||
* This means it can be used to safely delete a smart pointer referring to an open stream.
|
||||
*/
|
||||
struct StreamDeleterFunctor {
|
||||
void operator()(AudioStream *audioStream) {
|
||||
if (audioStream) {
|
||||
audioStream->close();
|
||||
}
|
||||
delete audioStream;
|
||||
}
|
||||
};
|
||||
} // namespace oboe
|
||||
|
||||
#endif /* OBOE_STREAM_H_ */
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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_STREAM_BASE_H_
|
||||
#define OBOE_STREAM_BASE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "oboe/AudioStreamCallback.h"
|
||||
#include "oboe/Definitions.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* Base class containing parameters for audio streams and builders.
|
||||
**/
|
||||
class AudioStreamBase {
|
||||
|
||||
public:
|
||||
|
||||
AudioStreamBase() {}
|
||||
|
||||
virtual ~AudioStreamBase() = default;
|
||||
|
||||
// This class only contains primitives so we can use default constructor and copy methods.
|
||||
|
||||
/**
|
||||
* Default copy constructor
|
||||
*/
|
||||
AudioStreamBase(const AudioStreamBase&) = default;
|
||||
|
||||
/**
|
||||
* Default assignment operator
|
||||
*/
|
||||
AudioStreamBase& operator=(const AudioStreamBase&) = default;
|
||||
|
||||
/**
|
||||
* @return number of channels, for example 2 for stereo, or kUnspecified
|
||||
*/
|
||||
int32_t getChannelCount() const { return mChannelCount; }
|
||||
|
||||
/**
|
||||
* @return Direction::Input or Direction::Output
|
||||
*/
|
||||
Direction getDirection() const { return mDirection; }
|
||||
|
||||
/**
|
||||
* @return sample rate for the stream or kUnspecified
|
||||
*/
|
||||
int32_t getSampleRate() const { return mSampleRate; }
|
||||
|
||||
/**
|
||||
* @deprecated use `getFramesPerDataCallback` instead.
|
||||
*/
|
||||
int32_t getFramesPerCallback() const { return getFramesPerDataCallback(); }
|
||||
|
||||
/**
|
||||
* @return the number of frames in each data callback or kUnspecified.
|
||||
*/
|
||||
int32_t getFramesPerDataCallback() const { return mFramesPerCallback; }
|
||||
|
||||
/**
|
||||
* @return the audio sample format (e.g. Float or I16)
|
||||
*/
|
||||
AudioFormat getFormat() const { return mFormat; }
|
||||
|
||||
/**
|
||||
* Query the maximum number of frames that can be filled without blocking.
|
||||
* If the stream has been closed the last known value will be returned.
|
||||
*
|
||||
* @return buffer size
|
||||
*/
|
||||
virtual int32_t getBufferSizeInFrames() { return mBufferSizeInFrames; }
|
||||
|
||||
/**
|
||||
* @return capacityInFrames or kUnspecified
|
||||
*/
|
||||
virtual int32_t getBufferCapacityInFrames() const { return mBufferCapacityInFrames; }
|
||||
|
||||
/**
|
||||
* @return the sharing mode of the stream.
|
||||
*/
|
||||
SharingMode getSharingMode() const { return mSharingMode; }
|
||||
|
||||
/**
|
||||
* @return the performance mode of the stream.
|
||||
*/
|
||||
PerformanceMode getPerformanceMode() const { return mPerformanceMode; }
|
||||
|
||||
/**
|
||||
* @return the device ID of the stream.
|
||||
*/
|
||||
int32_t getDeviceId() const { return mDeviceId; }
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* @return the data callback object for this stream, if set.
|
||||
*/
|
||||
AudioStreamDataCallback *getDataCallback() const {
|
||||
return mDataCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* @return the error callback object for this stream, if set.
|
||||
*/
|
||||
AudioStreamErrorCallback *getErrorCallback() const {
|
||||
return mErrorCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a data callback was set for this stream
|
||||
*/
|
||||
bool isDataCallbackSpecified() const {
|
||||
return mDataCallback != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that if the app does not set an error callback then a
|
||||
* default one may be provided.
|
||||
* @return true if an error callback was set for this stream
|
||||
*/
|
||||
bool isErrorCallbackSpecified() const {
|
||||
return mErrorCallback != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the usage for this stream.
|
||||
*/
|
||||
Usage getUsage() const { return mUsage; }
|
||||
|
||||
/**
|
||||
* @return the stream's content type.
|
||||
*/
|
||||
ContentType getContentType() const { return mContentType; }
|
||||
|
||||
/**
|
||||
* @return the stream's input preset.
|
||||
*/
|
||||
InputPreset getInputPreset() const { return mInputPreset; }
|
||||
|
||||
/**
|
||||
* @return the stream's session ID allocation strategy (None or Allocate).
|
||||
*/
|
||||
SessionId getSessionId() const { return mSessionId; }
|
||||
|
||||
/**
|
||||
* @return true if Oboe can convert channel counts to achieve optimal results.
|
||||
*/
|
||||
bool isChannelConversionAllowed() const {
|
||||
return mChannelConversionAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if Oboe can convert data formats to achieve optimal results.
|
||||
*/
|
||||
bool isFormatConversionAllowed() const {
|
||||
return mFormatConversionAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether and how Oboe can convert sample rates to achieve optimal results.
|
||||
*/
|
||||
SampleRateConversionQuality getSampleRateConversionQuality() const {
|
||||
return mSampleRateConversionQuality;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The callback which will be fired when new data is ready to be read/written. **/
|
||||
AudioStreamDataCallback *mDataCallback = nullptr;
|
||||
|
||||
/** The callback which will be fired when an error or a disconnect occurs. **/
|
||||
AudioStreamErrorCallback *mErrorCallback = nullptr;
|
||||
|
||||
/** Number of audio frames which will be requested in each callback */
|
||||
int32_t mFramesPerCallback = kUnspecified;
|
||||
/** Stream channel count */
|
||||
int32_t mChannelCount = kUnspecified;
|
||||
/** Stream sample rate */
|
||||
int32_t mSampleRate = kUnspecified;
|
||||
/** Stream audio device ID */
|
||||
int32_t mDeviceId = kUnspecified;
|
||||
/** Stream buffer capacity specified as a number of audio frames */
|
||||
int32_t mBufferCapacityInFrames = kUnspecified;
|
||||
/** Stream buffer size specified as a number of audio frames */
|
||||
int32_t mBufferSizeInFrames = kUnspecified;
|
||||
|
||||
/** Stream sharing mode */
|
||||
SharingMode mSharingMode = SharingMode::Shared;
|
||||
/** Format of audio frames */
|
||||
AudioFormat mFormat = AudioFormat::Unspecified;
|
||||
/** Stream direction */
|
||||
Direction mDirection = Direction::Output;
|
||||
/** Stream performance mode */
|
||||
PerformanceMode mPerformanceMode = PerformanceMode::None;
|
||||
|
||||
/** Stream usage. Only active on Android 28+ */
|
||||
Usage mUsage = Usage::Media;
|
||||
/** Stream content type. Only active on Android 28+ */
|
||||
ContentType mContentType = ContentType::Music;
|
||||
/** Stream input preset. Only active on Android 28+
|
||||
* TODO InputPreset::Unspecified should be considered as a possible default alternative.
|
||||
*/
|
||||
InputPreset mInputPreset = InputPreset::VoiceRecognition;
|
||||
/** Stream session ID allocation strategy. Only active on Android 28+ */
|
||||
SessionId mSessionId = SessionId::None;
|
||||
|
||||
/** Control the name of the package creating the stream. Only active on Android 31+ */
|
||||
std::string mPackageName;
|
||||
/** Control the attribution tag of the context creating the stream. Only active on Android 31+ */
|
||||
std::string mAttributionTag;
|
||||
|
||||
// Control whether Oboe can convert channel counts to achieve optimal results.
|
||||
bool mChannelConversionAllowed = false;
|
||||
// Control whether Oboe can convert data formats to achieve optimal results.
|
||||
bool mFormatConversionAllowed = false;
|
||||
// Control whether and how Oboe can convert sample rates to achieve optimal results.
|
||||
SampleRateConversionQuality mSampleRateConversionQuality = SampleRateConversionQuality::None;
|
||||
|
||||
/** Validate stream parameters that might not be checked in lower layers */
|
||||
virtual Result isValidConfig() {
|
||||
switch (mFormat) {
|
||||
case AudioFormat::Unspecified:
|
||||
case AudioFormat::I16:
|
||||
case AudioFormat::Float:
|
||||
case AudioFormat::I24:
|
||||
case AudioFormat::I32:
|
||||
break;
|
||||
|
||||
default:
|
||||
return Result::ErrorInvalidFormat;
|
||||
}
|
||||
|
||||
switch (mSampleRateConversionQuality) {
|
||||
case SampleRateConversionQuality::None:
|
||||
case SampleRateConversionQuality::Fastest:
|
||||
case SampleRateConversionQuality::Low:
|
||||
case SampleRateConversionQuality::Medium:
|
||||
case SampleRateConversionQuality::High:
|
||||
case SampleRateConversionQuality::Best:
|
||||
return Result::OK;
|
||||
default:
|
||||
return Result::ErrorIllegalArgument;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif /* OBOE_STREAM_BASE_H_ */
|
||||
@@ -1,520 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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_STREAM_BUILDER_H_
|
||||
#define OBOE_STREAM_BUILDER_H_
|
||||
|
||||
#include "oboe/Definitions.h"
|
||||
#include "oboe/AudioStreamBase.h"
|
||||
#include "ResultWithValue.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
// This depends on AudioStream, so we use forward declaration, it will close and delete the stream
|
||||
struct StreamDeleterFunctor;
|
||||
using ManagedStream = std::unique_ptr<AudioStream, StreamDeleterFunctor>;
|
||||
|
||||
/**
|
||||
* Factory class for an audio Stream.
|
||||
*/
|
||||
class AudioStreamBuilder : public AudioStreamBase {
|
||||
public:
|
||||
|
||||
AudioStreamBuilder() : AudioStreamBase() {}
|
||||
|
||||
AudioStreamBuilder(const AudioStreamBase &audioStreamBase): AudioStreamBase(audioStreamBase) {}
|
||||
|
||||
/**
|
||||
* Request a specific number of channels.
|
||||
*
|
||||
* Default is kUnspecified. If the value is unspecified then
|
||||
* the application should query for the actual value after the stream is opened.
|
||||
*/
|
||||
AudioStreamBuilder *setChannelCount(int channelCount) {
|
||||
mChannelCount = channelCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the direction for a stream. The default is Direction::Output.
|
||||
*
|
||||
* @param direction Direction::Output or Direction::Input
|
||||
*/
|
||||
AudioStreamBuilder *setDirection(Direction direction) {
|
||||
mDirection = direction;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a specific sample rate in Hz.
|
||||
*
|
||||
* Default is kUnspecified. If the value is unspecified then
|
||||
* the application should query for the actual value after the stream is opened.
|
||||
*
|
||||
* Technically, this should be called the "frame rate" or "frames per second",
|
||||
* because it refers to the number of complete frames transferred per second.
|
||||
* But it is traditionally called "sample rate". Se we use that term.
|
||||
*
|
||||
*/
|
||||
AudioStreamBuilder *setSampleRate(int32_t sampleRate) {
|
||||
mSampleRate = sampleRate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `setFramesPerDataCallback` instead.
|
||||
*/
|
||||
AudioStreamBuilder *setFramesPerCallback(int framesPerCallback) {
|
||||
return setFramesPerDataCallback(framesPerCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a specific number of frames for the data callback.
|
||||
*
|
||||
* Default is kUnspecified. If the value is unspecified then
|
||||
* the actual number may vary from callback to callback.
|
||||
*
|
||||
* If an application can handle a varying number of frames then we recommend
|
||||
* leaving this unspecified. This allow the underlying API to optimize
|
||||
* the callbacks. But if your application is, for example, doing FFTs or other block
|
||||
* oriented operations, then call this function to get the sizes you need.
|
||||
*
|
||||
* @param framesPerCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setFramesPerDataCallback(int framesPerCallback) {
|
||||
mFramesPerCallback = framesPerCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a sample data format, for example Format::Float.
|
||||
*
|
||||
* Default is Format::Unspecified. If the value is unspecified then
|
||||
* the application should query for the actual value after the stream is opened.
|
||||
*/
|
||||
AudioStreamBuilder *setFormat(AudioFormat format) {
|
||||
mFormat = format;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the requested buffer capacity in frames.
|
||||
* BufferCapacityInFrames is the maximum possible BufferSizeInFrames.
|
||||
*
|
||||
* The final stream capacity may differ. For AAudio it should be at least this big.
|
||||
* For OpenSL ES, it could be smaller.
|
||||
*
|
||||
* Default is kUnspecified.
|
||||
*
|
||||
* @param bufferCapacityInFrames the desired buffer capacity in frames or kUnspecified
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setBufferCapacityInFrames(int32_t bufferCapacityInFrames) {
|
||||
mBufferCapacityInFrames = bufferCapacityInFrames;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio API which will be requested when opening the stream. No guarantees that this is
|
||||
* the API which will actually be used. Query the stream itself to find out the API which is
|
||||
* being used.
|
||||
*
|
||||
* If you do not specify the API, then AAudio will be used if isAAudioRecommended()
|
||||
* returns true. Otherwise OpenSL ES will be used.
|
||||
*
|
||||
* @return the requested audio API
|
||||
*/
|
||||
AudioApi getAudioApi() const { return mAudioApi; }
|
||||
|
||||
/**
|
||||
* If you leave this unspecified then Oboe will choose the best API
|
||||
* for the device and SDK version at runtime.
|
||||
*
|
||||
* This should almost always be left unspecified, except for debugging purposes.
|
||||
* Specifying AAudio will force Oboe to use AAudio on 8.0, which is extremely risky.
|
||||
* Specifying OpenSLES should mainly be used to test legacy performance/functionality.
|
||||
*
|
||||
* If the caller requests AAudio and it is supported then AAudio will be used.
|
||||
*
|
||||
* @param audioApi Must be AudioApi::Unspecified, AudioApi::OpenSLES or AudioApi::AAudio.
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setAudioApi(AudioApi audioApi) {
|
||||
mAudioApi = audioApi;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the AAudio API supported on this device?
|
||||
*
|
||||
* AAudio was introduced in the Oreo 8.0 release.
|
||||
*
|
||||
* @return true if supported
|
||||
*/
|
||||
static bool isAAudioSupported();
|
||||
|
||||
/**
|
||||
* Is the AAudio API recommended this device?
|
||||
*
|
||||
* AAudio may be supported but not recommended because of version specific issues.
|
||||
* AAudio is not recommended for Android 8.0 or earlier versions.
|
||||
*
|
||||
* @return true if recommended
|
||||
*/
|
||||
static bool isAAudioRecommended();
|
||||
|
||||
/**
|
||||
* Request a mode for sharing the device.
|
||||
* The requested sharing mode may not be available.
|
||||
* So the application should query for the actual mode after the stream is opened.
|
||||
*
|
||||
* @param sharingMode SharingMode::Shared or SharingMode::Exclusive
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setSharingMode(SharingMode sharingMode) {
|
||||
mSharingMode = sharingMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a performance level for the stream.
|
||||
* This will determine the latency, the power consumption, and the level of
|
||||
* protection from glitches.
|
||||
*
|
||||
* @param performanceMode for example, PerformanceMode::LowLatency
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setPerformanceMode(PerformanceMode performanceMode) {
|
||||
mPerformanceMode = performanceMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the intended use case for an output stream.
|
||||
*
|
||||
* The system will use this information to optimize the behavior of the stream.
|
||||
* This could, for example, affect how volume and focus is handled for the stream.
|
||||
* The usage is ignored for input streams.
|
||||
*
|
||||
* The default, if you do not call this function, is Usage::Media.
|
||||
*
|
||||
* Added in API level 28.
|
||||
*
|
||||
* @param usage the desired usage, eg. Usage::Game
|
||||
*/
|
||||
AudioStreamBuilder *setUsage(Usage usage) {
|
||||
mUsage = usage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of audio data that an output stream will carry.
|
||||
*
|
||||
* The system will use this information to optimize the behavior of the stream.
|
||||
* This could, for example, affect whether a stream is paused when a notification occurs.
|
||||
* The contentType is ignored for input streams.
|
||||
*
|
||||
* The default, if you do not call this function, is ContentType::Music.
|
||||
*
|
||||
* Added in API level 28.
|
||||
*
|
||||
* @param contentType the type of audio data, eg. ContentType::Speech
|
||||
*/
|
||||
AudioStreamBuilder *setContentType(ContentType contentType) {
|
||||
mContentType = contentType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input (capture) preset for the stream.
|
||||
*
|
||||
* The system will use this information to optimize the behavior of the stream.
|
||||
* This could, for example, affect which microphones are used and how the
|
||||
* recorded data is processed.
|
||||
*
|
||||
* The default, if you do not call this function, is InputPreset::VoiceRecognition.
|
||||
* That is because VoiceRecognition is the preset with the lowest latency
|
||||
* on many platforms.
|
||||
*
|
||||
* Added in API level 28.
|
||||
*
|
||||
* @param inputPreset the desired configuration for recording
|
||||
*/
|
||||
AudioStreamBuilder *setInputPreset(InputPreset inputPreset) {
|
||||
mInputPreset = inputPreset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Set the requested session ID.
|
||||
*
|
||||
* The session ID can be used to associate a stream with effects processors.
|
||||
* The effects are controlled using the Android AudioEffect Java API.
|
||||
*
|
||||
* The default, if you do not call this function, is SessionId::None.
|
||||
*
|
||||
* If set to SessionId::Allocate then a session ID will be allocated
|
||||
* when the stream is opened.
|
||||
*
|
||||
* The allocated session ID can be obtained by calling AudioStream::getSessionId()
|
||||
* and then used with this function when opening another stream.
|
||||
* This allows effects to be shared between streams.
|
||||
*
|
||||
* Session IDs from Oboe can be used the Android Java APIs and vice versa.
|
||||
* So a session ID from an Oboe stream can be passed to Java
|
||||
* and effects applied using the Java AudioEffect API.
|
||||
*
|
||||
* Allocated session IDs will always be positive and nonzero.
|
||||
*
|
||||
* Added in API level 28.
|
||||
*
|
||||
* @param sessionId an allocated sessionID or SessionId::Allocate
|
||||
*/
|
||||
AudioStreamBuilder *setSessionId(SessionId sessionId) {
|
||||
mSessionId = sessionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a stream to a specific audio input/output device given an audio device ID.
|
||||
*
|
||||
* In most cases, the primary device will be the appropriate device to use, and the
|
||||
* deviceId can be left kUnspecified.
|
||||
*
|
||||
* On Android, for example, the ID could be obtained from the Java AudioManager.
|
||||
* AudioManager.getDevices() returns an array of AudioDeviceInfo[], which contains
|
||||
* a getId() method (as well as other type information), that should be passed
|
||||
* to this method.
|
||||
*
|
||||
*
|
||||
* Note that when using OpenSL ES, this will be ignored and the created
|
||||
* stream will have deviceId kUnspecified.
|
||||
*
|
||||
* @param deviceId device identifier or kUnspecified
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setDeviceId(int32_t deviceId) {
|
||||
mDeviceId = deviceId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies an object to handle data related callbacks from the underlying API.
|
||||
*
|
||||
* <strong>Important: See AudioStreamCallback for restrictions on what may be called
|
||||
* from the callback methods.</strong>
|
||||
*
|
||||
* @param dataCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setDataCallback(oboe::AudioStreamDataCallback *dataCallback) {
|
||||
mDataCallback = dataCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies an object to handle error related callbacks from the underlying API.
|
||||
* This can occur when a stream is disconnected because a headset is plugged in or unplugged.
|
||||
* It can also occur if the audio service fails or if an exclusive stream is stolen by
|
||||
* another stream.
|
||||
*
|
||||
* <strong>Important: See AudioStreamCallback for restrictions on what may be called
|
||||
* from the callback methods.</strong>
|
||||
*
|
||||
* <strong>When an error callback occurs, the associated stream must be stopped and closed
|
||||
* in a separate thread.</strong>
|
||||
*
|
||||
* @param errorCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setErrorCallback(oboe::AudioStreamErrorCallback *errorCallback) {
|
||||
mErrorCallback = errorCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies an object to handle data or error related callbacks from the underlying API.
|
||||
*
|
||||
* This is the equivalent of calling both setDataCallback() and setErrorCallback().
|
||||
*
|
||||
* <strong>Important: See AudioStreamCallback for restrictions on what may be called
|
||||
* from the callback methods.</strong>
|
||||
*
|
||||
* When an error callback occurs, the associated stream will be stopped and closed in a separate thread.
|
||||
*
|
||||
* A note on why the streamCallback parameter is a raw pointer rather than a smart pointer:
|
||||
*
|
||||
* The caller should retain ownership of the object streamCallback points to. At first glance weak_ptr may seem like
|
||||
* a good candidate for streamCallback as this implies temporary ownership. However, a weak_ptr can only be created
|
||||
* from a shared_ptr. A shared_ptr incurs some performance overhead. The callback object is likely to be accessed
|
||||
* every few milliseconds when the stream requires new data so this overhead is something we want to avoid.
|
||||
*
|
||||
* This leaves a raw pointer as the logical type choice. The only caveat being that the caller must not destroy
|
||||
* the callback before the stream has been closed.
|
||||
*
|
||||
* @param streamCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setCallback(AudioStreamCallback *streamCallback) {
|
||||
// Use the same callback object for both, dual inheritance.
|
||||
mDataCallback = streamCallback;
|
||||
mErrorCallback = streamCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true then Oboe might convert channel counts to achieve optimal results.
|
||||
* On some versions of Android for example, stereo streams could not use a FAST track.
|
||||
* So a mono stream might be used instead and duplicated to two channels.
|
||||
* On some devices, mono streams might be broken, so a stereo stream might be opened
|
||||
* and converted to mono.
|
||||
*
|
||||
* Default is true.
|
||||
*/
|
||||
AudioStreamBuilder *setChannelConversionAllowed(bool allowed) {
|
||||
mChannelConversionAllowed = allowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true then Oboe might convert data formats to achieve optimal results.
|
||||
* On some versions of Android, for example, a float stream could not get a
|
||||
* low latency data path. So an I16 stream might be opened and converted to float.
|
||||
*
|
||||
* Default is false.
|
||||
*/
|
||||
AudioStreamBuilder *setFormatConversionAllowed(bool allowed) {
|
||||
mFormatConversionAllowed = allowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the quality of the sample rate converter in Oboe.
|
||||
*
|
||||
* If set to None then Oboe will not do sample rate conversion. But the underlying APIs might
|
||||
* still do sample rate conversion if you specify a sample rate.
|
||||
* That can prevent you from getting a low latency stream.
|
||||
*
|
||||
* If you do the conversion in Oboe then you might still get a low latency stream.
|
||||
*
|
||||
* Default is SampleRateConversionQuality::None
|
||||
*/
|
||||
AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) {
|
||||
mSampleRateConversionQuality = quality;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare the name of the package creating the stream.
|
||||
*
|
||||
* This is usually Context#getPackageName()
|
||||
*
|
||||
* The default, if you do not call this function, is a random package in the calling uid.
|
||||
*
|
||||
* Added in API level 31.
|
||||
*
|
||||
* @param packageName packageName of the calling app.
|
||||
*/
|
||||
AudioStreamBuilder *setPackageName(std::string packageName) {
|
||||
mPackageName = packageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare the attribution tag of the context creating the stream.
|
||||
*
|
||||
* This is usually Context#getAttributionTag()
|
||||
*
|
||||
* The default, if you do not call this function, is the default attribution tag.
|
||||
*
|
||||
* Added in API level 31.
|
||||
*
|
||||
* @param attributionTag attributionTag of the calling context.
|
||||
*/
|
||||
AudioStreamBuilder *setAttributionTag(std::string attributionTag) {
|
||||
mAttributionTag = attributionTag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if AAudio will be used based on the current settings.
|
||||
*/
|
||||
bool willUseAAudio() const {
|
||||
return (mAudioApi == AudioApi::AAudio && isAAudioSupported())
|
||||
|| (mAudioApi == AudioApi::Unspecified && isAAudioRecommended());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and open a stream object based on the current settings.
|
||||
*
|
||||
* The caller owns the pointer to the AudioStream object
|
||||
* and must delete it when finished.
|
||||
*
|
||||
* @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
|
||||
* @param stream pointer to a variable to receive the stream address
|
||||
* @return OBOE_OK if successful or a negative error code
|
||||
*/
|
||||
Result openStream(AudioStream **stream);
|
||||
|
||||
/**
|
||||
* Create and open a stream object based on the current settings.
|
||||
*
|
||||
* The caller shares the pointer to the AudioStream object.
|
||||
* The shared_ptr is used internally by Oboe to prevent the stream from being
|
||||
* deleted while it is being used by callbacks.
|
||||
*
|
||||
* @param stream reference to a shared_ptr to receive the stream address
|
||||
* @return OBOE_OK if successful or a negative error code
|
||||
*/
|
||||
Result openStream(std::shared_ptr<oboe::AudioStream> &stream);
|
||||
|
||||
/**
|
||||
* Create and open a ManagedStream object based on the current builder state.
|
||||
*
|
||||
* The caller must create a unique ptr, and pass by reference so it can be
|
||||
* modified to point to an opened stream. The caller owns the unique ptr,
|
||||
* and it will be automatically closed and deleted when going out of scope.
|
||||
*
|
||||
* @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
|
||||
* @param stream Reference to the ManagedStream (uniqueptr) used to keep track of stream
|
||||
* @return OBOE_OK if successful or a negative error code.
|
||||
*/
|
||||
Result openManagedStream(ManagedStream &stream);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @param other
|
||||
* @return true if channels, format and sample rate match
|
||||
*/
|
||||
bool isCompatible(AudioStreamBase &other);
|
||||
|
||||
/**
|
||||
* Create an AudioStream object. The AudioStream must be opened before use.
|
||||
*
|
||||
* The caller owns the pointer.
|
||||
*
|
||||
* @return pointer to an AudioStream object or nullptr.
|
||||
*/
|
||||
oboe::AudioStream *build();
|
||||
|
||||
AudioApi mAudioApi = AudioApi::Unspecified;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif /* OBOE_STREAM_BUILDER_H_ */
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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_STREAM_CALLBACK_H
|
||||
#define OBOE_STREAM_CALLBACK_H
|
||||
|
||||
#include "oboe/Definitions.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
class AudioStream;
|
||||
|
||||
/**
|
||||
* AudioStreamDataCallback defines a callback interface for
|
||||
* moving data to/from an audio stream using `onAudioReady`
|
||||
* 2) being alerted when a stream has an error using `onError*` methods
|
||||
*
|
||||
* It is used with AudioStreamBuilder::setDataCallback().
|
||||
*/
|
||||
|
||||
class AudioStreamDataCallback {
|
||||
public:
|
||||
virtual ~AudioStreamDataCallback() = default;
|
||||
|
||||
/**
|
||||
* A buffer is ready for processing.
|
||||
*
|
||||
* For an output stream, this function should render and write numFrames of data
|
||||
* in the stream's current data format to the audioData buffer.
|
||||
*
|
||||
* For an input stream, this function should read and process numFrames of data
|
||||
* from the audioData buffer.
|
||||
*
|
||||
* The audio data is passed through the buffer. So do NOT call read() or
|
||||
* write() on the stream that is making the callback.
|
||||
*
|
||||
* Note that numFrames can vary unless AudioStreamBuilder::setFramesPerCallback()
|
||||
* is called.
|
||||
*
|
||||
* Also note that this callback function should be considered a "real-time" function.
|
||||
* It must not do anything that could cause an unbounded delay because that can cause the
|
||||
* audio to glitch or pop.
|
||||
*
|
||||
* These are things the function should NOT do:
|
||||
* <ul>
|
||||
* <li>allocate memory using, for example, malloc() or new</li>
|
||||
* <li>any file operations such as opening, closing, reading or writing</li>
|
||||
* <li>any network operations such as streaming</li>
|
||||
* <li>use any mutexes or other synchronization primitives</li>
|
||||
* <li>sleep</li>
|
||||
* <li>oboeStream->stop(), pause(), flush() or close()</li>
|
||||
* <li>oboeStream->read()</li>
|
||||
* <li>oboeStream->write()</li>
|
||||
* </ul>
|
||||
*
|
||||
* The following are OK to call from the data callback:
|
||||
* <ul>
|
||||
* <li>oboeStream->get*()</li>
|
||||
* <li>oboe::convertToText()</li>
|
||||
* <li>oboeStream->setBufferSizeInFrames()</li>
|
||||
* </ul>
|
||||
*
|
||||
* If you need to move data, eg. MIDI commands, in or out of the callback function then
|
||||
* we recommend the use of non-blocking techniques such as an atomic FIFO.
|
||||
*
|
||||
* @param audioStream pointer to the associated stream
|
||||
* @param audioData buffer containing input data or a place to put output data
|
||||
* @param numFrames number of frames to be processed
|
||||
* @return DataCallbackResult::Continue or DataCallbackResult::Stop
|
||||
*/
|
||||
virtual DataCallbackResult onAudioReady(
|
||||
AudioStream *audioStream,
|
||||
void *audioData,
|
||||
int32_t numFrames) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* AudioStreamErrorCallback defines a callback interface for
|
||||
* being alerted when a stream has an error or is disconnected
|
||||
* using `onError*` methods.
|
||||
*
|
||||
* It is used with AudioStreamBuilder::setErrorCallback().
|
||||
*/
|
||||
class AudioStreamErrorCallback {
|
||||
public:
|
||||
virtual ~AudioStreamErrorCallback() = default;
|
||||
|
||||
/**
|
||||
* This will be called before other `onError` methods when an error occurs on a stream,
|
||||
* such as when the stream is disconnected.
|
||||
*
|
||||
* It can be used to override and customize the normal error processing.
|
||||
* Use of this method is considered an advanced technique.
|
||||
* It might, for example, be used if an app want to use a high level lock when
|
||||
* closing and reopening a stream.
|
||||
* Or it might be used when an app want to signal a management thread that handles
|
||||
* all of the stream state.
|
||||
*
|
||||
* If this method returns false it indicates that the stream has *not been stopped and closed
|
||||
* by the application. In this case it will be stopped by Oboe in the following way:
|
||||
* onErrorBeforeClose() will be called, then the stream will be closed and onErrorAfterClose()
|
||||
* will be closed.
|
||||
*
|
||||
* If this method returns true it indicates that the stream *has* been stopped and closed
|
||||
* by the application and Oboe will not do this.
|
||||
* In that case, the app MUST stop() and close() the stream.
|
||||
*
|
||||
* This method will be called on a thread created by Oboe.
|
||||
*
|
||||
* @param audioStream pointer to the associated stream
|
||||
* @param error
|
||||
* @return true if the stream has been stopped and closed, false if not
|
||||
*/
|
||||
virtual bool onError(AudioStream* /* audioStream */, Result /* error */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will be called when an error occurs on a stream,
|
||||
* such as when the stream is disconnected,
|
||||
* and if onError() returns false (indicating that the error has not already been handled).
|
||||
*
|
||||
* Note that this will be called on a thread created by Oboe.
|
||||
*
|
||||
* The underlying stream will already be stopped by Oboe but not yet closed.
|
||||
* So the stream can be queried.
|
||||
*
|
||||
* Do not close or delete the stream in this method because it will be
|
||||
* closed after this method returns.
|
||||
*
|
||||
* @param audioStream pointer to the associated stream
|
||||
* @param error
|
||||
*/
|
||||
virtual void onErrorBeforeClose(AudioStream* /* audioStream */, Result /* error */) {}
|
||||
|
||||
/**
|
||||
* This will be called when an error occurs on a stream,
|
||||
* such as when the stream is disconnected,
|
||||
* and if onError() returns false (indicating that the error has not already been handled).
|
||||
*
|
||||
* The underlying AAudio or OpenSL ES stream will already be stopped AND closed by Oboe.
|
||||
* So the underlying stream cannot be referenced.
|
||||
* But you can still query most parameters.
|
||||
*
|
||||
* This callback could be used to reopen a new stream on another device.
|
||||
*
|
||||
* @param audioStream pointer to the associated stream
|
||||
* @param error
|
||||
*/
|
||||
virtual void onErrorAfterClose(AudioStream* /* audioStream */, Result /* error */) {}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* AudioStreamCallback defines a callback interface for:
|
||||
*
|
||||
* 1) moving data to/from an audio stream using `onAudioReady`
|
||||
* 2) being alerted when a stream has an error using `onError*` methods
|
||||
*
|
||||
* It is used with AudioStreamBuilder::setCallback().
|
||||
*
|
||||
* It combines the interfaces defined by AudioStreamDataCallback and AudioStreamErrorCallback.
|
||||
* This was the original callback object. We now recommend using the individual interfaces
|
||||
* and using setDataCallback() and setErrorCallback().
|
||||
*
|
||||
* @deprecated Use `AudioStreamDataCallback` and `AudioStreamErrorCallback` instead
|
||||
*/
|
||||
class AudioStreamCallback : public AudioStreamDataCallback,
|
||||
public AudioStreamErrorCallback {
|
||||
public:
|
||||
virtual ~AudioStreamCallback() = default;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_STREAM_CALLBACK_H
|
||||
@@ -1,545 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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_DEFINITIONS_H
|
||||
#define OBOE_DEFINITIONS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
// Oboe needs to be able to build on old NDKs so we use hard coded constants.
|
||||
// The correctness of these constants is verified in "aaudio/AAudioLoader.cpp".
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* Represents any attribute, property or value which hasn't been specified.
|
||||
*/
|
||||
constexpr int32_t kUnspecified = 0;
|
||||
|
||||
// TODO: Investigate using std::chrono
|
||||
/**
|
||||
* The number of nanoseconds in a microsecond. 1,000.
|
||||
*/
|
||||
constexpr int64_t kNanosPerMicrosecond = 1000;
|
||||
|
||||
/**
|
||||
* The number of nanoseconds in a millisecond. 1,000,000.
|
||||
*/
|
||||
constexpr int64_t kNanosPerMillisecond = kNanosPerMicrosecond * 1000;
|
||||
|
||||
/**
|
||||
* The number of milliseconds in a second. 1,000.
|
||||
*/
|
||||
constexpr int64_t kMillisPerSecond = 1000;
|
||||
|
||||
/**
|
||||
* The number of nanoseconds in a second. 1,000,000,000.
|
||||
*/
|
||||
constexpr int64_t kNanosPerSecond = kNanosPerMillisecond * kMillisPerSecond;
|
||||
|
||||
/**
|
||||
* The state of the audio stream.
|
||||
*/
|
||||
enum class StreamState : int32_t { // aaudio_stream_state_t
|
||||
Uninitialized = 0, // AAUDIO_STREAM_STATE_UNINITIALIZED,
|
||||
Unknown = 1, // AAUDIO_STREAM_STATE_UNKNOWN,
|
||||
Open = 2, // AAUDIO_STREAM_STATE_OPEN,
|
||||
Starting = 3, // AAUDIO_STREAM_STATE_STARTING,
|
||||
Started = 4, // AAUDIO_STREAM_STATE_STARTED,
|
||||
Pausing = 5, // AAUDIO_STREAM_STATE_PAUSING,
|
||||
Paused = 6, // AAUDIO_STREAM_STATE_PAUSED,
|
||||
Flushing = 7, // AAUDIO_STREAM_STATE_FLUSHING,
|
||||
Flushed = 8, // AAUDIO_STREAM_STATE_FLUSHED,
|
||||
Stopping = 9, // AAUDIO_STREAM_STATE_STOPPING,
|
||||
Stopped = 10, // AAUDIO_STREAM_STATE_STOPPED,
|
||||
Closing = 11, // AAUDIO_STREAM_STATE_CLOSING,
|
||||
Closed = 12, // AAUDIO_STREAM_STATE_CLOSED,
|
||||
Disconnected = 13, // AAUDIO_STREAM_STATE_DISCONNECTED,
|
||||
};
|
||||
|
||||
/**
|
||||
* The direction of the stream.
|
||||
*/
|
||||
enum class Direction : int32_t { // aaudio_direction_t
|
||||
|
||||
/**
|
||||
* Used for playback.
|
||||
*/
|
||||
Output = 0, // AAUDIO_DIRECTION_OUTPUT,
|
||||
|
||||
/**
|
||||
* Used for recording.
|
||||
*/
|
||||
Input = 1, // AAUDIO_DIRECTION_INPUT,
|
||||
};
|
||||
|
||||
/**
|
||||
* The format of audio samples.
|
||||
*/
|
||||
enum class AudioFormat : int32_t { // aaudio_format_t
|
||||
/**
|
||||
* Invalid format.
|
||||
*/
|
||||
Invalid = -1, // AAUDIO_FORMAT_INVALID,
|
||||
|
||||
/**
|
||||
* Unspecified format. Format will be decided by Oboe.
|
||||
*/
|
||||
Unspecified = 0, // AAUDIO_FORMAT_UNSPECIFIED,
|
||||
|
||||
/**
|
||||
* Signed 16-bit integers.
|
||||
*/
|
||||
I16 = 1, // AAUDIO_FORMAT_PCM_I16,
|
||||
|
||||
/**
|
||||
* Single precision floating point.
|
||||
*
|
||||
* This is the recommended format for most applications.
|
||||
* But note that the use of Float may prevent the opening of
|
||||
* a low-latency input path on OpenSL ES or Legacy AAudio streams.
|
||||
*/
|
||||
Float = 2, // AAUDIO_FORMAT_PCM_FLOAT,
|
||||
|
||||
/**
|
||||
* Signed 24-bit integers, packed into 3 bytes.
|
||||
*
|
||||
* Note that the use of this format does not guarantee that
|
||||
* the full precision will be provided. The underlying device may
|
||||
* be using I16 format.
|
||||
*
|
||||
* Added in API 31 (S).
|
||||
*/
|
||||
I24 = 3, // AAUDIO_FORMAT_PCM_I24_PACKED
|
||||
|
||||
/**
|
||||
* Signed 32-bit integers.
|
||||
*
|
||||
* Note that the use of this format does not guarantee that
|
||||
* the full precision will be provided. The underlying device may
|
||||
* be using I16 format.
|
||||
*
|
||||
* Added in API 31 (S).
|
||||
*/
|
||||
I32 = 4, // AAUDIO_FORMAT_PCM_I32
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The result of an audio callback.
|
||||
*/
|
||||
enum class DataCallbackResult : int32_t { // aaudio_data_callback_result_t
|
||||
// Indicates to the caller that the callbacks should continue.
|
||||
Continue = 0, // AAUDIO_CALLBACK_RESULT_CONTINUE,
|
||||
|
||||
// Indicates to the caller that the callbacks should stop immediately.
|
||||
Stop = 1, // AAUDIO_CALLBACK_RESULT_STOP,
|
||||
};
|
||||
|
||||
/**
|
||||
* The result of an operation. All except the `OK` result indicates that an error occurred.
|
||||
* The `Result` can be converted into a human readable string using `convertToText`.
|
||||
*/
|
||||
enum class Result : int32_t { // aaudio_result_t
|
||||
OK = 0, // AAUDIO_OK
|
||||
ErrorBase = -900, // AAUDIO_ERROR_BASE,
|
||||
ErrorDisconnected = -899, // AAUDIO_ERROR_DISCONNECTED,
|
||||
ErrorIllegalArgument = -898, // AAUDIO_ERROR_ILLEGAL_ARGUMENT,
|
||||
ErrorInternal = -896, // AAUDIO_ERROR_INTERNAL,
|
||||
ErrorInvalidState = -895, // AAUDIO_ERROR_INVALID_STATE,
|
||||
ErrorInvalidHandle = -892, // AAUDIO_ERROR_INVALID_HANDLE,
|
||||
ErrorUnimplemented = -890, // AAUDIO_ERROR_UNIMPLEMENTED,
|
||||
ErrorUnavailable = -889, // AAUDIO_ERROR_UNAVAILABLE,
|
||||
ErrorNoFreeHandles = -888, // AAUDIO_ERROR_NO_FREE_HANDLES,
|
||||
ErrorNoMemory = -887, // AAUDIO_ERROR_NO_MEMORY,
|
||||
ErrorNull = -886, // AAUDIO_ERROR_NULL,
|
||||
ErrorTimeout = -885, // AAUDIO_ERROR_TIMEOUT,
|
||||
ErrorWouldBlock = -884, // AAUDIO_ERROR_WOULD_BLOCK,
|
||||
ErrorInvalidFormat = -883, // AAUDIO_ERROR_INVALID_FORMAT,
|
||||
ErrorOutOfRange = -882, // AAUDIO_ERROR_OUT_OF_RANGE,
|
||||
ErrorNoService = -881, // AAUDIO_ERROR_NO_SERVICE,
|
||||
ErrorInvalidRate = -880, // AAUDIO_ERROR_INVALID_RATE,
|
||||
// Reserved for future AAudio result types
|
||||
Reserved1,
|
||||
Reserved2,
|
||||
Reserved3,
|
||||
Reserved4,
|
||||
Reserved5,
|
||||
Reserved6,
|
||||
Reserved7,
|
||||
Reserved8,
|
||||
Reserved9,
|
||||
Reserved10,
|
||||
ErrorClosed = -869,
|
||||
};
|
||||
|
||||
/**
|
||||
* The sharing mode of the audio stream.
|
||||
*/
|
||||
enum class SharingMode : int32_t { // aaudio_sharing_mode_t
|
||||
|
||||
/**
|
||||
* This will be the only stream using a particular source or sink.
|
||||
* This mode will provide the lowest possible latency.
|
||||
* You should close EXCLUSIVE streams immediately when you are not using them.
|
||||
*
|
||||
* If you do not need the lowest possible latency then we recommend using Shared,
|
||||
* which is the default.
|
||||
*/
|
||||
Exclusive = 0, // AAUDIO_SHARING_MODE_EXCLUSIVE,
|
||||
|
||||
/**
|
||||
* Multiple applications can share the same device.
|
||||
* The data from output streams will be mixed by the audio service.
|
||||
* The data for input streams will be distributed by the audio service.
|
||||
*
|
||||
* This will have higher latency than the EXCLUSIVE mode.
|
||||
*/
|
||||
Shared = 1, // AAUDIO_SHARING_MODE_SHARED,
|
||||
};
|
||||
|
||||
/**
|
||||
* The performance mode of the audio stream.
|
||||
*/
|
||||
enum class PerformanceMode : int32_t { // aaudio_performance_mode_t
|
||||
|
||||
/**
|
||||
* No particular performance needs. Default.
|
||||
*/
|
||||
None = 10, // AAUDIO_PERFORMANCE_MODE_NONE,
|
||||
|
||||
/**
|
||||
* Extending battery life is most important.
|
||||
*/
|
||||
PowerSaving = 11, // AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
|
||||
|
||||
/**
|
||||
* Reducing latency is most important.
|
||||
*/
|
||||
LowLatency = 12, // AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
|
||||
};
|
||||
|
||||
/**
|
||||
* The underlying audio API used by the audio stream.
|
||||
*/
|
||||
enum class AudioApi : int32_t {
|
||||
/**
|
||||
* Try to use AAudio. If not available then use OpenSL ES.
|
||||
*/
|
||||
Unspecified = kUnspecified,
|
||||
|
||||
/**
|
||||
* Use OpenSL ES.
|
||||
*/
|
||||
OpenSLES,
|
||||
|
||||
/**
|
||||
* Try to use AAudio. Fail if unavailable.
|
||||
*/
|
||||
AAudio
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the quality of the sample rate conversion performed by Oboe.
|
||||
* Higher quality will require more CPU load.
|
||||
* Higher quality conversion will probably be implemented using a sinc based resampler.
|
||||
*/
|
||||
enum class SampleRateConversionQuality : int32_t {
|
||||
/**
|
||||
* No conversion by Oboe. Underlying APIs may still do conversion.
|
||||
*/
|
||||
None,
|
||||
/**
|
||||
* Fastest conversion but may not sound great.
|
||||
* This may be implemented using bilinear interpolation.
|
||||
*/
|
||||
Fastest,
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
/**
|
||||
* Highest quality conversion, which may be expensive in terms of CPU.
|
||||
*/
|
||||
Best,
|
||||
};
|
||||
|
||||
/**
|
||||
* The Usage attribute expresses *why* you are playing a sound, what is this sound used for.
|
||||
* This information is used by certain platforms or routing policies
|
||||
* to make more refined volume or routing decisions.
|
||||
*
|
||||
* Note that these match the equivalent values in AudioAttributes in the Android Java API.
|
||||
*
|
||||
* This attribute only has an effect on Android API 28+.
|
||||
*/
|
||||
enum class Usage : int32_t { // aaudio_usage_t
|
||||
/**
|
||||
* Use this for streaming media, music performance, video, podcasts, etcetera.
|
||||
*/
|
||||
Media = 1, // AAUDIO_USAGE_MEDIA
|
||||
|
||||
/**
|
||||
* Use this for voice over IP, telephony, etcetera.
|
||||
*/
|
||||
VoiceCommunication = 2, // AAUDIO_USAGE_VOICE_COMMUNICATION
|
||||
|
||||
/**
|
||||
* Use this for sounds associated with telephony such as busy tones, DTMF, etcetera.
|
||||
*/
|
||||
VoiceCommunicationSignalling = 3, // AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
|
||||
|
||||
/**
|
||||
* Use this to demand the users attention.
|
||||
*/
|
||||
Alarm = 4, // AAUDIO_USAGE_ALARM
|
||||
|
||||
/**
|
||||
* Use this for notifying the user when a message has arrived or some
|
||||
* other background event has occured.
|
||||
*/
|
||||
Notification = 5, // AAUDIO_USAGE_NOTIFICATION
|
||||
|
||||
/**
|
||||
* Use this when the phone rings.
|
||||
*/
|
||||
NotificationRingtone = 6, // AAUDIO_USAGE_NOTIFICATION_RINGTONE
|
||||
|
||||
/**
|
||||
* Use this to attract the users attention when, for example, the battery is low.
|
||||
*/
|
||||
NotificationEvent = 10, // AAUDIO_USAGE_NOTIFICATION_EVENT
|
||||
|
||||
/**
|
||||
* Use this for screen readers, etcetera.
|
||||
*/
|
||||
AssistanceAccessibility = 11, // AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY
|
||||
|
||||
/**
|
||||
* Use this for driving or navigation directions.
|
||||
*/
|
||||
AssistanceNavigationGuidance = 12, // AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
|
||||
|
||||
/**
|
||||
* Use this for user interface sounds, beeps, etcetera.
|
||||
*/
|
||||
AssistanceSonification = 13, // AAUDIO_USAGE_ASSISTANCE_SONIFICATION
|
||||
|
||||
/**
|
||||
* Use this for game audio and sound effects.
|
||||
*/
|
||||
Game = 14, // AAUDIO_USAGE_GAME
|
||||
|
||||
/**
|
||||
* Use this for audio responses to user queries, audio instructions or help utterances.
|
||||
*/
|
||||
Assistant = 16, // AAUDIO_USAGE_ASSISTANT
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The ContentType attribute describes *what* you are playing.
|
||||
* It expresses the general category of the content. This information is optional.
|
||||
* But in case it is known (for instance {@link Movie} for a
|
||||
* movie streaming service or {@link Speech} for
|
||||
* an audio book application) this information might be used by the audio framework to
|
||||
* enforce audio focus.
|
||||
*
|
||||
* Note that these match the equivalent values in AudioAttributes in the Android Java API.
|
||||
*
|
||||
* This attribute only has an effect on Android API 28+.
|
||||
*/
|
||||
enum ContentType : int32_t { // aaudio_content_type_t
|
||||
|
||||
/**
|
||||
* Use this for spoken voice, audio books, etcetera.
|
||||
*/
|
||||
Speech = 1, // AAUDIO_CONTENT_TYPE_SPEECH
|
||||
|
||||
/**
|
||||
* Use this for pre-recorded or live music.
|
||||
*/
|
||||
Music = 2, // AAUDIO_CONTENT_TYPE_MUSIC
|
||||
|
||||
/**
|
||||
* Use this for a movie or video soundtrack.
|
||||
*/
|
||||
Movie = 3, // AAUDIO_CONTENT_TYPE_MOVIE
|
||||
|
||||
/**
|
||||
* Use this for sound is designed to accompany a user action,
|
||||
* such as a click or beep sound made when the user presses a button.
|
||||
*/
|
||||
Sonification = 4, // AAUDIO_CONTENT_TYPE_SONIFICATION
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the audio source.
|
||||
* An audio source defines both a default physical source of audio signal, and a recording
|
||||
* configuration.
|
||||
*
|
||||
* Note that these match the equivalent values in MediaRecorder.AudioSource in the Android Java API.
|
||||
*
|
||||
* This attribute only has an effect on Android API 28+.
|
||||
*/
|
||||
enum InputPreset : int32_t { // aaudio_input_preset_t
|
||||
/**
|
||||
* Use this preset when other presets do not apply.
|
||||
*/
|
||||
Generic = 1, // AAUDIO_INPUT_PRESET_GENERIC
|
||||
|
||||
/**
|
||||
* Use this preset when recording video.
|
||||
*/
|
||||
Camcorder = 5, // AAUDIO_INPUT_PRESET_CAMCORDER
|
||||
|
||||
/**
|
||||
* Use this preset when doing speech recognition.
|
||||
*/
|
||||
VoiceRecognition = 6, // AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
|
||||
|
||||
/**
|
||||
* Use this preset when doing telephony or voice messaging.
|
||||
*/
|
||||
VoiceCommunication = 7, // AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION
|
||||
|
||||
/**
|
||||
* Use this preset to obtain an input with no effects.
|
||||
* Note that this input will not have automatic gain control
|
||||
* so the recorded volume may be very low.
|
||||
*/
|
||||
Unprocessed = 9, // AAUDIO_INPUT_PRESET_UNPROCESSED
|
||||
|
||||
/**
|
||||
* Use this preset for capturing audio meant to be processed in real time
|
||||
* and played back for live performance (e.g karaoke).
|
||||
* The capture path will minimize latency and coupling with playback path.
|
||||
*/
|
||||
VoicePerformance = 10, // AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This attribute can be used to allocate a session ID to the audio stream.
|
||||
*
|
||||
* This attribute only has an effect on Android API 28+.
|
||||
*/
|
||||
enum SessionId {
|
||||
/**
|
||||
* Do not allocate a session ID.
|
||||
* Effects cannot be used with this stream.
|
||||
* Default.
|
||||
*/
|
||||
None = -1, // AAUDIO_SESSION_ID_NONE
|
||||
|
||||
/**
|
||||
* Allocate a session ID that can be used to attach and control
|
||||
* effects using the Java AudioEffects API.
|
||||
* Note that the use of this flag may result in higher latency.
|
||||
*
|
||||
* Note that this matches the value of AudioManager.AUDIO_SESSION_ID_GENERATE.
|
||||
*/
|
||||
Allocate = 0, // AAUDIO_SESSION_ID_ALLOCATE
|
||||
};
|
||||
|
||||
/**
|
||||
* The channel count of the audio stream. The underlying type is `int32_t`.
|
||||
* Use of this enum is convenient to avoid "magic"
|
||||
* numbers when specifying the channel count.
|
||||
*
|
||||
* For example, you can write
|
||||
* `builder.setChannelCount(ChannelCount::Stereo)`
|
||||
* rather than `builder.setChannelCount(2)`
|
||||
*
|
||||
*/
|
||||
enum ChannelCount : int32_t {
|
||||
/**
|
||||
* Audio channel count definition, use Mono or Stereo
|
||||
*/
|
||||
Unspecified = kUnspecified,
|
||||
|
||||
/**
|
||||
* Use this for mono audio
|
||||
*/
|
||||
Mono = 1,
|
||||
|
||||
/**
|
||||
* Use this for stereo audio.
|
||||
*/
|
||||
Stereo = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* On API 16 to 26 OpenSL ES will be used. When using OpenSL ES the optimal values for sampleRate and
|
||||
* framesPerBurst are not known by the native code.
|
||||
* On API 17+ these values should be obtained from the AudioManager using this code:
|
||||
*
|
||||
* <pre><code>
|
||||
* // Note that this technique only works for built-in speakers and headphones.
|
||||
* AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
* String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
|
||||
* int defaultSampleRate = Integer.parseInt(sampleRateStr);
|
||||
* String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
|
||||
* int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr);
|
||||
* </code></pre>
|
||||
*
|
||||
* It can then be passed down to Oboe through JNI.
|
||||
*
|
||||
* AAudio will get the optimal framesPerBurst from the HAL and will ignore this value.
|
||||
*/
|
||||
class DefaultStreamValues {
|
||||
|
||||
public:
|
||||
|
||||
/** The default sample rate to use when opening new audio streams */
|
||||
static int32_t SampleRate;
|
||||
/** The default frames per burst to use when opening new audio streams */
|
||||
static int32_t FramesPerBurst;
|
||||
/** The default channel count to use when opening new audio streams */
|
||||
static int32_t ChannelCount;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The time at which the frame at `position` was presented
|
||||
*/
|
||||
struct FrameTimestamp {
|
||||
int64_t position; // in frames
|
||||
int64_t timestamp; // in nanoseconds
|
||||
};
|
||||
|
||||
class OboeGlobals {
|
||||
public:
|
||||
|
||||
static bool areWorkaroundsEnabled() {
|
||||
return mWorkaroundsEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable this when writing tests to reproduce bugs in AAudio or OpenSL ES
|
||||
* that have workarounds in Oboe.
|
||||
* @param enabled
|
||||
*/
|
||||
static void setWorkaroundsEnabled(bool enabled) {
|
||||
mWorkaroundsEnabled = enabled;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool mWorkaroundsEnabled;
|
||||
};
|
||||
} // namespace oboe
|
||||
|
||||
#endif // OBOE_DEFINITIONS_H
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* 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_LATENCY_TUNER_
|
||||
#define OBOE_LATENCY_TUNER_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include "oboe/Definitions.h"
|
||||
#include "oboe/AudioStream.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* LatencyTuner can be used to dynamically tune the latency of an output stream.
|
||||
* It adjusts the stream's bufferSize by monitoring the number of underruns.
|
||||
*
|
||||
* This only affects the latency associated with the first level of buffering that is closest
|
||||
* to the application. It does not affect low latency in the HAL, or touch latency in the UI.
|
||||
*
|
||||
* Call tune() right before returning from your data callback function if using callbacks.
|
||||
* Call tune() right before calling write() if using blocking writes.
|
||||
*
|
||||
* If you want to see the ongoing results of this tuning process then call
|
||||
* stream->getBufferSize() periodically.
|
||||
*
|
||||
*/
|
||||
class LatencyTuner {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a new LatencyTuner object which will act on the given audio stream
|
||||
*
|
||||
* @param stream the stream who's latency will be tuned
|
||||
*/
|
||||
explicit LatencyTuner(AudioStream &stream);
|
||||
|
||||
/**
|
||||
* Construct a new LatencyTuner object which will act on the given audio stream.
|
||||
*
|
||||
* @param stream the stream who's latency will be tuned
|
||||
* @param the maximum buffer size which the tune() operation will set the buffer size to
|
||||
*/
|
||||
explicit LatencyTuner(AudioStream &stream, int32_t maximumBufferSize);
|
||||
|
||||
/**
|
||||
* Adjust the bufferSizeInFrames to optimize latency.
|
||||
* It will start with a low latency and then raise it if an underrun occurs.
|
||||
*
|
||||
* Latency tuning is only supported for AAudio.
|
||||
*
|
||||
* @return OK or negative error, ErrorUnimplemented for OpenSL ES
|
||||
*/
|
||||
Result tune();
|
||||
|
||||
/**
|
||||
* This may be called from another thread. Then tune() will call reset(),
|
||||
* which will lower the latency to the minimum and then allow it to rise back up
|
||||
* if there are glitches.
|
||||
*
|
||||
* This is typically called in response to a user decision to minimize latency. In other words,
|
||||
* call this from a button handler.
|
||||
*/
|
||||
void requestReset();
|
||||
|
||||
/**
|
||||
* @return true if the audio stream's buffer size is at the maximum value. If no maximum value
|
||||
* was specified when constructing the LatencyTuner then the value of
|
||||
* stream->getBufferCapacityInFrames is used
|
||||
*/
|
||||
bool isAtMaximumBufferSize();
|
||||
|
||||
/**
|
||||
* Set the minimum bufferSize in frames that is used when the tuner is reset.
|
||||
* You may wish to call requestReset() after calling this.
|
||||
* @param bufferSize
|
||||
*/
|
||||
void setMinimumBufferSize(int32_t bufferSize) {
|
||||
mMinimumBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
int32_t getMinimumBufferSize() const {
|
||||
return mMinimumBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount the bufferSize will be incremented while tuning.
|
||||
* By default, this will be one burst.
|
||||
*
|
||||
* Note that AAudio will quantize the buffer size to a multiple of the burstSize.
|
||||
* So the final buffer sizes may not be a multiple of this increment.
|
||||
*
|
||||
* @param sizeIncrement
|
||||
*/
|
||||
void setBufferSizeIncrement(int32_t sizeIncrement) {
|
||||
mBufferSizeIncrement = sizeIncrement;
|
||||
}
|
||||
|
||||
int32_t getBufferSizeIncrement() const {
|
||||
return mBufferSizeIncrement;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Drop the latency down to the minimum and then let it rise back up.
|
||||
* This is useful if a glitch caused the latency to increase and it hasn't gone back down.
|
||||
*
|
||||
* This should only be called in the same thread as tune().
|
||||
*/
|
||||
void reset();
|
||||
|
||||
enum class State {
|
||||
Idle,
|
||||
Active,
|
||||
AtMax,
|
||||
Unsupported
|
||||
} ;
|
||||
|
||||
// arbitrary number of calls to wait before bumping up the latency
|
||||
static constexpr int32_t kIdleCount = 8;
|
||||
static constexpr int32_t kDefaultNumBursts = 2;
|
||||
|
||||
AudioStream &mStream;
|
||||
State mState = State::Idle;
|
||||
int32_t mMaxBufferSize = 0;
|
||||
int32_t mPreviousXRuns = 0;
|
||||
int32_t mIdleCountDown = 0;
|
||||
int32_t mMinimumBufferSize;
|
||||
int32_t mBufferSizeIncrement;
|
||||
std::atomic<int32_t> mLatencyTriggerRequests{0}; // TODO user atomic requester from AAudio
|
||||
std::atomic<int32_t> mLatencyTriggerResponses{0};
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif // OBOE_LATENCY_TUNER_
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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_OBOE_H
|
||||
#define OBOE_OBOE_H
|
||||
|
||||
/**
|
||||
* \mainpage API reference
|
||||
*
|
||||
* All documentation is found in the <a href="namespaceoboe.html">oboe namespace section</a>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "oboe/Definitions.h"
|
||||
#include "oboe/ResultWithValue.h"
|
||||
#include "oboe/LatencyTuner.h"
|
||||
#include "oboe/AudioStream.h"
|
||||
#include "oboe/AudioStreamBase.h"
|
||||
#include "oboe/AudioStreamBuilder.h"
|
||||
#include "oboe/Utilities.h"
|
||||
#include "oboe/Version.h"
|
||||
#include "oboe/StabilizedCallback.h"
|
||||
|
||||
#endif //OBOE_OBOE_H
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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 OBOE_RESULT_WITH_VALUE_H
|
||||
#define OBOE_RESULT_WITH_VALUE_H
|
||||
|
||||
#include "oboe/Definitions.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* A ResultWithValue can store both the result of an operation (either OK or an error) and a value.
|
||||
*
|
||||
* It has been designed for cases where the caller needs to know whether an operation succeeded and,
|
||||
* if it did, a value which was obtained during the operation.
|
||||
*
|
||||
* For example, when reading from a stream the caller needs to know the result of the read operation
|
||||
* and, if it was successful, how many frames were read. Note that ResultWithValue can be evaluated
|
||||
* as a boolean so it's simple to check whether the result is OK.
|
||||
*
|
||||
* <code>
|
||||
* ResultWithValue<int32_t> resultOfRead = myStream.read(&buffer, numFrames, timeoutNanoseconds);
|
||||
*
|
||||
* if (resultOfRead) {
|
||||
* LOGD("Frames read: %d", resultOfRead.value());
|
||||
* } else {
|
||||
* LOGD("Error reading from stream: %s", resultOfRead.error());
|
||||
* }
|
||||
* </code>
|
||||
*/
|
||||
template <typename T>
|
||||
class ResultWithValue {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a ResultWithValue containing an error result.
|
||||
*
|
||||
* @param error The error
|
||||
*/
|
||||
ResultWithValue(oboe::Result error)
|
||||
: mValue{}
|
||||
, mError(error) {}
|
||||
|
||||
/**
|
||||
* Construct a ResultWithValue containing an OK result and a value.
|
||||
*
|
||||
* @param value the value to store
|
||||
*/
|
||||
explicit ResultWithValue(T value)
|
||||
: mValue(value)
|
||||
, mError(oboe::Result::OK) {}
|
||||
|
||||
/**
|
||||
* Get the result.
|
||||
*
|
||||
* @return the result
|
||||
*/
|
||||
oboe::Result error() const {
|
||||
return mError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value
|
||||
* @return
|
||||
*/
|
||||
T value() const {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if OK
|
||||
*/
|
||||
explicit operator bool() const { return mError == oboe::Result::OK; }
|
||||
|
||||
/**
|
||||
* Quick way to check for an error.
|
||||
*
|
||||
* The caller could write something like this:
|
||||
* <code>
|
||||
* if (!result) { printf("Got error %s\n", convertToText(result.error())); }
|
||||
* </code>
|
||||
*
|
||||
* @return true if an error occurred
|
||||
*/
|
||||
bool operator !() const { return mError != oboe::Result::OK; }
|
||||
|
||||
/**
|
||||
* Implicitly convert to a Result. This enables easy comparison with Result values. Example:
|
||||
*
|
||||
* <code>
|
||||
* ResultWithValue result = openStream();
|
||||
* if (result == Result::ErrorNoMemory){ // tell user they're out of memory }
|
||||
* </code>
|
||||
*/
|
||||
operator Result() const {
|
||||
return mError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ResultWithValue from a number. If the number is positive the ResultWithValue will
|
||||
* have a result of Result::OK and the value will contain the number. If the number is negative
|
||||
* the result will be obtained from the negative number (numeric error codes can be found in
|
||||
* AAudio.h) and the value will be null.
|
||||
*
|
||||
*/
|
||||
static ResultWithValue<T> createBasedOnSign(T numericResult){
|
||||
|
||||
// Ensure that the type is either an integer or float
|
||||
static_assert(std::is_arithmetic<T>::value,
|
||||
"createBasedOnSign can only be called for numeric types (int or float)");
|
||||
|
||||
if (numericResult >= 0){
|
||||
return ResultWithValue<T>(numericResult);
|
||||
} else {
|
||||
return ResultWithValue<T>(static_cast<Result>(numericResult));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const T mValue;
|
||||
const oboe::Result mError;
|
||||
};
|
||||
|
||||
/**
|
||||
* If the result is `OK` then return the value, otherwise return a human-readable error message.
|
||||
*/
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream &strm, const ResultWithValue<T> &result) {
|
||||
if (!result) {
|
||||
strm << convertToText(result.error());
|
||||
} else {
|
||||
strm << result.value();
|
||||
}
|
||||
return strm;
|
||||
}
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
|
||||
#endif //OBOE_RESULT_WITH_VALUE_H
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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 OBOE_STABILIZEDCALLBACK_H
|
||||
#define OBOE_STABILIZEDCALLBACK_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "oboe/AudioStream.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
class StabilizedCallback : public AudioStreamCallback {
|
||||
|
||||
public:
|
||||
explicit StabilizedCallback(AudioStreamCallback *callback);
|
||||
|
||||
DataCallbackResult
|
||||
onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override;
|
||||
|
||||
void onErrorBeforeClose(AudioStream *oboeStream, Result error) override {
|
||||
return mCallback->onErrorBeforeClose(oboeStream, error);
|
||||
}
|
||||
|
||||
void onErrorAfterClose(AudioStream *oboeStream, Result error) override {
|
||||
|
||||
// Reset all fields now that the stream has been closed
|
||||
mFrameCount = 0;
|
||||
mEpochTimeNanos = 0;
|
||||
mOpsPerNano = 1;
|
||||
return mCallback->onErrorAfterClose(oboeStream, error);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
AudioStreamCallback *mCallback = nullptr;
|
||||
int64_t mFrameCount = 0;
|
||||
int64_t mEpochTimeNanos = 0;
|
||||
double mOpsPerNano = 1;
|
||||
|
||||
void generateLoad(int64_t durationNanos);
|
||||
};
|
||||
|
||||
/**
|
||||
* cpu_relax is an architecture specific method of telling the CPU that you don't want it to
|
||||
* do much work. asm volatile keeps the compiler from optimising these instructions out.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define cpu_relax() asm volatile("rep; nop" ::: "memory");
|
||||
|
||||
#elif defined(__arm__) || defined(__mips__)
|
||||
#define cpu_relax() asm volatile("":::"memory")
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
#define cpu_relax() asm volatile("yield" ::: "memory")
|
||||
|
||||
#else
|
||||
#error "cpu_relax is not defined for this architecture"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif //OBOE_STABILIZEDCALLBACK_H
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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_UTILITIES_H
|
||||
#define OBOE_UTILITIES_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
#include "oboe/Definitions.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* Convert an array of floats to an array of 16-bit integers.
|
||||
*
|
||||
* @param source the input array.
|
||||
* @param destination the output array.
|
||||
* @param numSamples the number of values to convert.
|
||||
*/
|
||||
void convertFloatToPcm16(const float *source, int16_t *destination, int32_t numSamples);
|
||||
|
||||
/**
|
||||
* Convert an array of 16-bit integers to an array of floats.
|
||||
*
|
||||
* @param source the input array.
|
||||
* @param destination the output array.
|
||||
* @param numSamples the number of values to convert.
|
||||
*/
|
||||
void convertPcm16ToFloat(const int16_t *source, float *destination, int32_t numSamples);
|
||||
|
||||
/**
|
||||
* @return the size of a sample of the given format in bytes or 0 if format is invalid
|
||||
*/
|
||||
int32_t convertFormatToSizeInBytes(AudioFormat format);
|
||||
|
||||
/**
|
||||
* The text is the ASCII symbol corresponding to the supplied Oboe enum value,
|
||||
* or an English message saying the value is unrecognized.
|
||||
* This is intended for developers to use when debugging.
|
||||
* It is not for displaying to users.
|
||||
*
|
||||
* @param input object to convert from. @see common/Utilities.cpp for concrete implementations
|
||||
* @return text representation of an Oboe enum value. There is no need to call free on this.
|
||||
*/
|
||||
template <typename FromType>
|
||||
const char * convertToText(FromType input);
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return the value of a named system property in a string or empty string
|
||||
*/
|
||||
std::string getPropertyString(const char * name);
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @param defaultValue
|
||||
* @return integer value associated with a property or the default value
|
||||
*/
|
||||
int getPropertyInteger(const char * name, int defaultValue);
|
||||
|
||||
/**
|
||||
* Return the version of the SDK that is currently running.
|
||||
*
|
||||
* For example, on Android, this would return 27 for Oreo 8.1.
|
||||
* If the version number cannot be determined then this will return -1.
|
||||
*
|
||||
* @return version number or -1
|
||||
*/
|
||||
int getSdkVersion();
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_UTILITIES_H
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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_VERSIONINFO_H
|
||||
#define OBOE_VERSIONINFO_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* A note on use of preprocessor defines:
|
||||
*
|
||||
* This is one of the few times when it's suitable to use preprocessor defines rather than constexpr
|
||||
* Why? Because C++11 requires a lot of boilerplate code to convert integers into compile-time
|
||||
* string literals. The preprocessor, despite it's lack of type checking, is more suited to the task
|
||||
*
|
||||
* See: https://stackoverflow.com/questions/6713420/c-convert-integer-to-string-at-compile-time/26824971#26824971
|
||||
*
|
||||
*/
|
||||
|
||||
// Type: 8-bit unsigned int. Min value: 0 Max value: 255. See below for description.
|
||||
#define OBOE_VERSION_MAJOR 1
|
||||
|
||||
// Type: 8-bit unsigned int. Min value: 0 Max value: 255. See below for description.
|
||||
#define OBOE_VERSION_MINOR 6
|
||||
|
||||
// Type: 16-bit unsigned int. Min value: 0 Max value: 65535. See below for description.
|
||||
#define OBOE_VERSION_PATCH 1
|
||||
|
||||
#define OBOE_STRINGIFY(x) #x
|
||||
#define OBOE_TOSTRING(x) OBOE_STRINGIFY(x)
|
||||
|
||||
// Type: String literal. See below for description.
|
||||
#define OBOE_VERSION_TEXT \
|
||||
OBOE_TOSTRING(OBOE_VERSION_MAJOR) "." \
|
||||
OBOE_TOSTRING(OBOE_VERSION_MINOR) "." \
|
||||
OBOE_TOSTRING(OBOE_VERSION_PATCH)
|
||||
|
||||
// Type: 32-bit unsigned int. See below for description.
|
||||
#define OBOE_VERSION_NUMBER ((OBOE_VERSION_MAJOR << 24) | (OBOE_VERSION_MINOR << 16) | OBOE_VERSION_PATCH)
|
||||
|
||||
namespace oboe {
|
||||
|
||||
const char * getVersionText();
|
||||
|
||||
/**
|
||||
* Oboe versioning object
|
||||
*/
|
||||
struct Version {
|
||||
/**
|
||||
* This is incremented when we make breaking API changes. Based loosely on https://semver.org/.
|
||||
*/
|
||||
static constexpr uint8_t Major = OBOE_VERSION_MAJOR;
|
||||
|
||||
/**
|
||||
* This is incremented when we add backwards compatible functionality. Or set to zero when MAJOR is
|
||||
* incremented.
|
||||
*/
|
||||
static constexpr uint8_t Minor = OBOE_VERSION_MINOR;
|
||||
|
||||
/**
|
||||
* This is incremented when we make backwards compatible bug fixes. Or set to zero when MINOR is
|
||||
* incremented.
|
||||
*/
|
||||
static constexpr uint16_t Patch = OBOE_VERSION_PATCH;
|
||||
|
||||
/**
|
||||
* Version string in the form MAJOR.MINOR.PATCH.
|
||||
*/
|
||||
static constexpr const char * Text = OBOE_VERSION_TEXT;
|
||||
|
||||
/**
|
||||
* Integer representation of the current Oboe library version. This will always increase when the
|
||||
* version number changes so can be compared using integer comparison.
|
||||
*/
|
||||
static constexpr uint32_t Number = OBOE_VERSION_NUMBER;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
#endif //OBOE_VERSIONINFO_H
|
||||
@@ -1 +0,0 @@
|
||||
{"abi":"arm64-v8a","api":21,"ndk":21,"stl":"c++_shared"}
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"abi":"armeabi-v7a","api":16,"ndk":21,"stl":"c++_shared"}
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"abi":"x86","api":16,"ndk":21,"stl":"c++_shared"}
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"abi":"x86_64","api":21,"ndk":21,"stl":"c++_shared"}
|
||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"export_libraries": [],
|
||||
"library_name": null,
|
||||
"android": {
|
||||
"export_libraries": [],
|
||||
"library_name": null
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
if(ANDROID AND NOT TARGET oboe::oboe)
|
||||
#set(OBOE_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/libs/android.${CMAKE_ANDROID_ARCH_ABI}/liboboe.so")
|
||||
#set(OBOE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
add_library(oboe::oboe SHARED IMPORTED)
|
||||
set_target_properties(oboe::oboe PROPERTIES
|
||||
IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/libs/android.${CMAKE_ANDROID_ARCH_ABI}/liboboe.so"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/include"
|
||||
)
|
||||
#mark_as_advanced(OBOE_LIBRARY OBOE_INCLUDE_DIR)
|
||||
endif()
|
||||
|
||||
#include(FindPackageHandleStandardArgs)
|
||||
#find_package_handle_standard_args(Oboe REQUIRED_VARS OBOE_LIBRARY OBOE_INCLUDE_DIR)
|
||||
@@ -1,14 +0,0 @@
|
||||
set(PACKAGE_FIND_VERSION_MAJOR 1)
|
||||
set(PACKAGE_FIND_VERSION_MINOR 6)
|
||||
set(PACKAGE_FIND_VERSION_PATCH 1)
|
||||
set(PACKAGE_FIND_VERSION_COUNT 3)
|
||||
set(PACKAGE_VERSION "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}.${PACKAGE_FIND_VERSION_PATCH}")
|
||||
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
Reference in New Issue
Block a user