mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-10-18 17:48:03 +00:00
Move dead submodules in-tree
Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
parent
c0cceff365
commit
6c655321e6
4081 changed files with 1185566 additions and 45 deletions
74
externals/oboe/include/oboe/AudioClock.h
vendored
Normal file
74
externals/oboe/include/oboe/AudioClock.h
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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_AUDIO_CLOCK_H
|
||||
#define OBOE_AUDIO_CLOCK_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ctime>
|
||||
#include "oboe/Definitions.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
class AudioClock {
|
||||
public:
|
||||
static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
|
||||
struct timespec time;
|
||||
int result = clock_gettime(clockId, &time);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
return (time.tv_sec * kNanosPerSecond) + time.tv_nsec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep until the specified time.
|
||||
*
|
||||
* @param nanoTime time to wake up
|
||||
* @param clockId CLOCK_MONOTONIC is default
|
||||
* @return 0 or a negative error, eg. -EINTR
|
||||
*/
|
||||
|
||||
static int sleepUntilNanoTime(int64_t nanoTime, clockid_t clockId = CLOCK_MONOTONIC) {
|
||||
struct timespec time;
|
||||
time.tv_sec = nanoTime / kNanosPerSecond;
|
||||
time.tv_nsec = nanoTime - (time.tv_sec * kNanosPerSecond);
|
||||
return 0 - clock_nanosleep(clockId, TIMER_ABSTIME, &time, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep for the specified number of nanoseconds in real-time.
|
||||
* Return immediately with 0 if a negative nanoseconds is specified.
|
||||
*
|
||||
* @param nanoseconds time to sleep
|
||||
* @param clockId CLOCK_REALTIME is default
|
||||
* @return 0 or a negative error, eg. -EINTR
|
||||
*/
|
||||
|
||||
static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_REALTIME) {
|
||||
if (nanoseconds > 0) {
|
||||
struct timespec time;
|
||||
time.tv_sec = nanoseconds / kNanosPerSecond;
|
||||
time.tv_nsec = nanoseconds - (time.tv_sec * kNanosPerSecond);
|
||||
return 0 - clock_nanosleep(clockId, 0, &time, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_AUDIO_CLOCK_H
|
765
externals/oboe/include/oboe/AudioStream.h
vendored
Normal file
765
externals/oboe/include/oboe/AudioStream.h
vendored
Normal file
|
@ -0,0 +1,765 @@
|
|||
/*
|
||||
* 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"
|
||||
#include "oboe/Utilities.h"
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the audio resources associated with a stream created by AAudioStreamBuilder_openStream().
|
||||
*
|
||||
* AAudioStream_close() should be called at some point after calling this function.
|
||||
*
|
||||
* After this call, the stream will be in AAUDIO_STREAM_STATE_CLOSING
|
||||
*
|
||||
* This function is useful if you want to release the audio resources immediately, but still allow
|
||||
* queries to the stream to occur from other threads. This often happens if you are monitoring
|
||||
* stream progress from a UI thread.
|
||||
*
|
||||
* NOTE: This function is only fully implemented for MMAP streams, which are low latency streams
|
||||
* supported by some devices. On other "Legacy" streams some audio resources will still be in use
|
||||
* and some callbacks may still be in process after this call.
|
||||
*
|
||||
* Available in AAudio since API level 30. Returns Result::ErrorUnimplemented otherwise.
|
||||
*
|
||||
* * @return either Result::OK or an error.
|
||||
*/
|
||||
virtual Result release() {
|
||||
return Result::ErrorUnimplemented;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*
|
||||
* This should only be used with Output streams. It will
|
||||
* be ignored for Input streams because they are generally kept as empty as possible.
|
||||
*
|
||||
* For OpenSL ES, this method only has an effect on output stream that do NOT
|
||||
* use a callback. The blocking writes goes into a buffer in Oboe and the size of that
|
||||
* buffer is controlled by this method.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* Note for compressed formats, bytes per frames is treated as 1 by convention.
|
||||
*
|
||||
* @return number of bytes in each audio frame.
|
||||
*/
|
||||
int32_t getBytesPerFrame() const {
|
||||
return isCompressedFormat(mFormat) ? 1 : 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.
|
||||
*
|
||||
* Note for compressed formats, they may not have a fixed bytes per sample. In that case,
|
||||
* this method will return 0 for compressed format.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* Note that due to issues in Android before R, we recommend NOT calling
|
||||
* this method from a data callback. See this tech note for more details.
|
||||
* https://github.com/google/oboe/wiki/TechNote_ReleaseBuffer
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* Note that due to issues in Android before R, we recommend NOT calling
|
||||
* this method from a data callback. See this tech note for more details.
|
||||
* https://github.com/google/oboe/wiki/TechNote_ReleaseBuffer
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* Note that due to issues in Android before R, we recommend NOT calling
|
||||
* this method from a data callback. See this tech note for more details.
|
||||
* https://github.com/google/oboe/wiki/TechNote_ReleaseBuffer
|
||||
*
|
||||
* See
|
||||
* @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.
|
||||
*
|
||||
* Starting with Oboe 1.7.1, the numFrames will be clipped internally against the
|
||||
* BufferCapacity minus BurstSize. This is to prevent trying to wait for more frames
|
||||
* than could possibly be available. In this case, the return value may be less than numFrames.
|
||||
* Note that there may still be glitching if numFrames is too high.
|
||||
*
|
||||
* @param numFrames requested 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;
|
||||
}
|
||||
|
||||
|
||||
int32_t getDelayBeforeCloseMillis() const {
|
||||
return mDelayBeforeCloseMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time to sleep before closing the internal stream.
|
||||
*
|
||||
* Sometimes a callback can occur shortly after a stream has been stopped and
|
||||
* even after a close! If the stream has been closed then the callback
|
||||
* might access memory that has been freed, which could cause a crash.
|
||||
* This seems to be more likely in Android P or earlier.
|
||||
* But it can also occur in later versions. By sleeping, we give time for
|
||||
* the callback threads to finish.
|
||||
*
|
||||
* Note that this only has an effect when OboeGlobals::areWorkaroundsEnabled() is true.
|
||||
*
|
||||
* @param delayBeforeCloseMillis time to sleep before close.
|
||||
*/
|
||||
void setDelayBeforeCloseMillis(int32_t delayBeforeCloseMillis) {
|
||||
mDelayBeforeCloseMillis = delayBeforeCloseMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable a device specific CPU performance hint.
|
||||
* Runtime benchmarks such as the callback duration may be used to
|
||||
* speed up the CPU and improve real-time performance.
|
||||
*
|
||||
* Note that this feature is device specific and may not be implemented.
|
||||
* Also the benefits may vary by device.
|
||||
*
|
||||
* The flag will be checked in the Oboe data callback. If it transitions from false to true
|
||||
* then the PerformanceHint feature will be started.
|
||||
* This only needs to be called once for each stream.
|
||||
*
|
||||
* You may want to enable this if you have a dynamically changing workload
|
||||
* and you notice that you are getting under-runs and glitches when your workload increases.
|
||||
* This might happen, for example, if you suddenly go from playing one note to
|
||||
* ten notes on a synthesizer.
|
||||
*
|
||||
* Try the "CPU Load" test in OboeTester if you would like to experiment with this interactively.
|
||||
*
|
||||
* On some devices, this may be implemented using the "ADPF" library.
|
||||
*
|
||||
* @param enabled true if you would like a performance boost, default is false
|
||||
*/
|
||||
void setPerformanceHintEnabled(bool enabled) {
|
||||
mPerformanceHintEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* This only tells you if the feature has been requested.
|
||||
* It does not tell you if the PerformanceHint feature is implemented or active on the device.
|
||||
*
|
||||
* @return true if set using setPerformanceHintEnabled().
|
||||
*/
|
||||
bool isPerformanceHintEnabled() {
|
||||
return mPerformanceHintEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to give the performance manager more information about your workload.
|
||||
* You can call this at the beginning of the callback when you figure
|
||||
* out what your workload will be.
|
||||
*
|
||||
* Call this if (1) you have called setPerformanceHintEnabled(true), and
|
||||
* (2) you have a varying workload, and
|
||||
* (3) you hear glitches when your workload suddenly increases.
|
||||
*
|
||||
* This might happen when you go from a single note to a big chord on a synthesizer.
|
||||
*
|
||||
* The workload can be in your own units. If you are synthesizing music
|
||||
* then the workload could be the number of active voices.
|
||||
* If your app is a game then it could be the number of sound effects.
|
||||
* The units are arbitrary. They just have to be proportional to
|
||||
* the estimated computational load. For example, if some of your voices take 20%
|
||||
* more computation than a basic voice then assign 6 units to the complex voice
|
||||
* and 5 units to the basic voice.
|
||||
*
|
||||
* The performance hint code can use this as an advance warning that the callback duration
|
||||
* will probably increase. Rather than wait for the long duration and possibly under-run,
|
||||
* we can boost the CPU immediately before we start doing the calculations.
|
||||
*
|
||||
* @param appWorkload workload in application units, such as number of voices
|
||||
* @return OK or an error such as ErrorInvalidState if the PerformanceHint was not enabled.
|
||||
*/
|
||||
virtual oboe::Result reportWorkload([[maybe_unused]] int32_t appWorkload) {
|
||||
return oboe::Result::ErrorUnimplemented;
|
||||
}
|
||||
|
||||
virtual oboe::Result setOffloadDelayPadding([[maybe_unused]] int32_t delayInFrames,
|
||||
[[maybe_unused]] int32_t paddingInFrames) {
|
||||
return Result::ErrorUnimplemented;
|
||||
}
|
||||
|
||||
virtual ResultWithValue<int32_t> getOffloadDelay() {
|
||||
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
|
||||
}
|
||||
|
||||
virtual ResultWithValue<int32_t> getOffloadPadding() {
|
||||
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
|
||||
}
|
||||
|
||||
virtual oboe::Result setOffloadEndOfStream() {
|
||||
return Result::ErrorUnimplemented;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should only be called as a stream is being opened.
|
||||
* Otherwise we might override setDelayBeforeCloseMillis().
|
||||
*/
|
||||
void calculateDefaultDelayBeforeCloseMillis();
|
||||
|
||||
/**
|
||||
* Try to avoid a race condition when closing.
|
||||
*/
|
||||
void sleepBeforeClose() {
|
||||
if (mDelayBeforeCloseMillis > 0) {
|
||||
usleep(mDelayBeforeCloseMillis * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This may be called internally at the beginning of a callback.
|
||||
*/
|
||||
virtual void beginPerformanceHintInCallback() {}
|
||||
|
||||
/**
|
||||
* This may be called internally at the end of a callback.
|
||||
* @param numFrames passed to the callback
|
||||
*/
|
||||
virtual void endPerformanceHintInCallback(int32_t /*numFrames*/) {}
|
||||
|
||||
/**
|
||||
* This will be called when the stream is closed just in case performance hints were enabled.
|
||||
*/
|
||||
virtual void closePerformanceHint() {}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
// Time to sleep in order to prevent a race condition with a callback after a close().
|
||||
// Two milliseconds may be enough but 10 msec is even safer.
|
||||
static constexpr int kMinDelayBeforeCloseMillis = 10;
|
||||
int32_t mDelayBeforeCloseMillis = kMinDelayBeforeCloseMillis;
|
||||
|
||||
private:
|
||||
|
||||
// Log the scheduler if it changes.
|
||||
void checkScheduler();
|
||||
int mPreviousScheduler = -1;
|
||||
|
||||
std::atomic<bool> mDataCallbackEnabled{false};
|
||||
std::atomic<bool> mErrorCallbackCalled{false};
|
||||
|
||||
std::atomic<bool> mPerformanceHintEnabled{false}; // set only by app
|
||||
};
|
||||
|
||||
/**
|
||||
* 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_ */
|
374
externals/oboe/include/oboe/AudioStreamBase.h
vendored
Normal file
374
externals/oboe/include/oboe/AudioStreamBase.h
vendored
Normal file
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
* 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 <vector>
|
||||
#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 mDeviceIds.empty() ? kUnspecified : mDeviceIds[0];
|
||||
}
|
||||
|
||||
std::vector<int32_t> getDeviceIds() const {
|
||||
return mDeviceIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* @return the presentation callback object for this stream, if set.
|
||||
*/
|
||||
std::shared_ptr<AudioStreamPresentationCallback> getPresentationCallback() const {
|
||||
return mSharedPresentationCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 true if a presentation callback was set for this stream
|
||||
*/
|
||||
bool isPresentationCallbackSpecified() const {
|
||||
return mSharedPresentationCallback != 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 whether the content of the stream is spatialized.
|
||||
*/
|
||||
bool isContentSpatialized() const { return mIsContentSpatialized; }
|
||||
|
||||
/**
|
||||
* @return the spatialization behavior for the stream.
|
||||
*/
|
||||
SpatializationBehavior getSpatializationBehavior() const { return mSpatializationBehavior; }
|
||||
|
||||
/**
|
||||
* Return the policy that determines whether the audio may or may not be captured
|
||||
* by other apps or the system.
|
||||
*
|
||||
* See AudioStreamBuilder_setAllowedCapturePolicy().
|
||||
*
|
||||
* Added in API level 29 to AAudio.
|
||||
*
|
||||
* @return the allowed capture policy, for example AllowedCapturePolicy::All
|
||||
*/
|
||||
AllowedCapturePolicy getAllowedCapturePolicy() const { return mAllowedCapturePolicy; }
|
||||
|
||||
/**
|
||||
* Return whether this input stream is marked as privacy sensitive.
|
||||
*
|
||||
* See AudioStreamBuilder_setPrivacySensitiveMode().
|
||||
*
|
||||
* Added in API level 30 to AAudio.
|
||||
*
|
||||
* @return PrivacySensitiveMode::Enabled if privacy sensitive,
|
||||
* PrivacySensitiveMode::Disabled if not privacy sensitive, and
|
||||
* PrivacySensitiveMode::Unspecified if API is not supported.
|
||||
*/
|
||||
PrivacySensitiveMode getPrivacySensitiveMode() const { return mPrivacySensitiveMode; }
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the stream's channel mask.
|
||||
*/
|
||||
ChannelMask getChannelMask() const {
|
||||
return mChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of channels for the hardware, for example 2 for stereo, or kUnspecified.
|
||||
*/
|
||||
int32_t getHardwareChannelCount() const { return mHardwareChannelCount; }
|
||||
|
||||
/**
|
||||
* @return hardware sample rate for the stream or kUnspecified
|
||||
*/
|
||||
int32_t getHardwareSampleRate() const { return mHardwareSampleRate; }
|
||||
|
||||
/**
|
||||
* @return the audio sample format of the hardware (e.g. Float or I16)
|
||||
*/
|
||||
AudioFormat getHardwareFormat() const { return mHardwareFormat; }
|
||||
|
||||
protected:
|
||||
/** The callback which will be fired when new data is ready to be read/written. **/
|
||||
AudioStreamDataCallback *mDataCallback = nullptr;
|
||||
std::shared_ptr<AudioStreamDataCallback> mSharedDataCallback;
|
||||
|
||||
/** The callback which will be fired when an error or a disconnect occurs. **/
|
||||
AudioStreamErrorCallback *mErrorCallback = nullptr;
|
||||
std::shared_ptr<AudioStreamErrorCallback> mSharedErrorCallback;
|
||||
|
||||
std::shared_ptr<AudioStreamPresentationCallback> mSharedPresentationCallback;
|
||||
|
||||
/** 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 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 channel mask. Only active on Android 32+ */
|
||||
ChannelMask mChannelMask = ChannelMask::Unspecified;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Allowed Capture Policy. Only active on Android 29+ */
|
||||
AllowedCapturePolicy mAllowedCapturePolicy = AllowedCapturePolicy::Unspecified;
|
||||
|
||||
/** Privacy Sensitive Mode. Only active on Android 30+ */
|
||||
PrivacySensitiveMode mPrivacySensitiveMode = PrivacySensitiveMode::Unspecified;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Whether the content is already spatialized. Only used on Android 32+ */
|
||||
bool mIsContentSpatialized = false;
|
||||
/** Spatialization Behavior. Only active on Android 32+ */
|
||||
SpatializationBehavior mSpatializationBehavior = SpatializationBehavior::Unspecified;
|
||||
|
||||
/** Hardware channel count. Only specified on Android 34+ AAudio streams */
|
||||
int32_t mHardwareChannelCount = kUnspecified;
|
||||
/** Hardware sample rate. Only specified on Android 34+ AAudio streams */
|
||||
int32_t mHardwareSampleRate = kUnspecified;
|
||||
/** Hardware format. Only specified on Android 34+ AAudio streams */
|
||||
AudioFormat mHardwareFormat = AudioFormat::Unspecified;
|
||||
|
||||
// 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::Medium;
|
||||
|
||||
std::vector<int32_t> mDeviceIds;
|
||||
|
||||
/** 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:
|
||||
case AudioFormat::IEC61937:
|
||||
case AudioFormat::MP3:
|
||||
case AudioFormat::AAC_LC:
|
||||
case AudioFormat::AAC_HE_V1:
|
||||
case AudioFormat::AAC_HE_V2:
|
||||
case AudioFormat::AAC_ELD:
|
||||
case AudioFormat::AAC_XHE:
|
||||
case AudioFormat::OPUS:
|
||||
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_ */
|
709
externals/oboe/include/oboe/AudioStreamBuilder.h
vendored
Normal file
709
externals/oboe/include/oboe/AudioStreamBuilder.h
vendored
Normal file
|
@ -0,0 +1,709 @@
|
|||
/*
|
||||
* 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 "oboe/Utilities.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.
|
||||
*
|
||||
* As the channel count here may be different from the corresponding channel count of
|
||||
* provided channel mask used in setChannelMask(). The last called will be respected
|
||||
* if this function and setChannelMask() are called.
|
||||
*/
|
||||
AudioStreamBuilder *setChannelCount(int channelCount) {
|
||||
mChannelCount = channelCount;
|
||||
mChannelMask = ChannelMask::Unspecified;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a specific channel mask.
|
||||
*
|
||||
* Default is kUnspecified. If the value is unspecified then the application
|
||||
* should query for the actual value after the stream is opened.
|
||||
*
|
||||
* As the corresponding channel count of provided channel mask here may be different
|
||||
* from the channel count used in setChannelCount(). The last called will be respected
|
||||
* if this function and setChannelCount() are called.
|
||||
*
|
||||
* As the setChannelMask API is available on Android 32+, this call will only take effects
|
||||
* on Android 32+.
|
||||
*/
|
||||
AudioStreamBuilder *setChannelMask(ChannelMask channelMask) {
|
||||
mChannelMask = channelMask;
|
||||
mChannelCount = getChannelCountFromChannelMask(channelMask);
|
||||
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.
|
||||
*
|
||||
* Calling setFramesPerDataCallback() does not guarantee anything about timing.
|
||||
* This just collects the data into a the number of frames that your app requires.
|
||||
* We encourage leaving this unspecified in most cases.
|
||||
*
|
||||
* If this number is larger than the burst size, some bursts will not receive a callback.
|
||||
* If this number is smaller than the burst size, there may be multiple callbacks in a single
|
||||
* burst.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* The ID could be obtained from the Java AudioManager.
|
||||
* AudioManager.getDevices() returns an array of AudioDeviceInfo,
|
||||
* which contains a getId() method. That ID can be passed to this function.
|
||||
*
|
||||
* It is possible that you may not get the device that you requested.
|
||||
* So if it is important to you, you should call
|
||||
* stream->getDeviceId() after the stream is opened to
|
||||
* verify the actual ID.
|
||||
*
|
||||
* 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) {
|
||||
mDeviceIds.clear();
|
||||
if (deviceId != kUnspecified) {
|
||||
mDeviceIds.push_back(deviceId);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether this stream audio may or may not be captured by other apps or the system.
|
||||
*
|
||||
* The default is AllowedCapturePolicy::Unspecified which maps to AAUDIO_ALLOW_CAPTURE_BY_ALL.
|
||||
*
|
||||
* Note that an application can also set its global policy, in which case the most restrictive
|
||||
* policy is always applied. See android.media.AudioAttributes.setAllowedCapturePolicy.
|
||||
*
|
||||
* Added in API level 29 to AAudio.
|
||||
*
|
||||
* @param inputPreset the desired level of opt-out from being captured.
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setAllowedCapturePolicy(AllowedCapturePolicy allowedCapturePolicy) {
|
||||
mAllowedCapturePolicy = allowedCapturePolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Indicates whether this input stream must be marked as privacy sensitive or not.
|
||||
*
|
||||
* When PrivacySensitiveMode::Enabled, this input stream is privacy sensitive and any
|
||||
* concurrent capture is not permitted.
|
||||
*
|
||||
* This is off (PrivacySensitiveMode::Disabled) by default except when the input preset is
|
||||
* InputPreset::VoiceRecognition or InputPreset::Camcorder
|
||||
*
|
||||
* Always takes precedence over default from input preset when set explicitly.
|
||||
*
|
||||
* Only relevant if the stream direction is Direction::Input and AAudio is used.
|
||||
*
|
||||
* Added in API level 30 to AAudio.
|
||||
*
|
||||
* @param privacySensitive PrivacySensitiveMode::Enabled if capture from this stream must be
|
||||
* marked as privacy sensitive, PrivacySensitiveMode::Disabled if stream should be marked as
|
||||
* not sensitive.
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setPrivacySensitiveMode(PrivacySensitiveMode privacySensitiveMode) {
|
||||
mPrivacySensitiveMode = privacySensitiveMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether the audio data of this output stream has already been processed for spatialization.
|
||||
*
|
||||
* If the stream has been processed for spatialization, setting this to true will prevent issues such as
|
||||
* double-processing on platforms that will spatialize audio data.
|
||||
*
|
||||
* This is false by default.
|
||||
*
|
||||
* Available since API level 32.
|
||||
*
|
||||
* @param isContentSpatialized whether the content is already spatialized
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setIsContentSpatialized(bool isContentSpatialized) {
|
||||
mIsContentSpatialized = isContentSpatialized;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the behavior affecting whether spatialization will be used.
|
||||
*
|
||||
* The AAudio system will use this information to select whether the stream will go through a
|
||||
* spatializer effect or not when the effect is supported and enabled.
|
||||
*
|
||||
* This is SpatializationBehavior::Never by default.
|
||||
*
|
||||
* Available since API level 32.
|
||||
*
|
||||
* @param spatializationBehavior the desired spatialization behavior
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setSpatializationBehavior(SpatializationBehavior spatializationBehavior) {
|
||||
mSpatializationBehavior = spatializationBehavior;
|
||||
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>
|
||||
*
|
||||
* We pass a shared_ptr so that the sharedDataCallback object cannot be deleted
|
||||
* before the stream is deleted.
|
||||
*
|
||||
* @param sharedDataCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setDataCallback(std::shared_ptr<AudioStreamDataCallback> sharedDataCallback) {
|
||||
// Use this raw pointer in the rest of the code to retain backwards compatibility.
|
||||
mDataCallback = sharedDataCallback.get();
|
||||
// Hold a shared_ptr to protect the raw pointer for the lifetime of the stream.
|
||||
mSharedDataCallback = sharedDataCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass a raw pointer to a data callback. This is not recommended because the dataCallback
|
||||
* object might get deleted by the app while it is being used.
|
||||
*
|
||||
* @deprecated Call setDataCallback(std::shared_ptr<AudioStreamDataCallback>) instead.
|
||||
* @param dataCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setDataCallback(AudioStreamDataCallback *dataCallback) {
|
||||
mDataCallback = dataCallback;
|
||||
mSharedDataCallback = nullptr;
|
||||
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.
|
||||
*
|
||||
* Note that error callbacks will only be called when a data callback has been specified
|
||||
* and the stream is started. If you are not using a data callback then the read(), write()
|
||||
* and requestStart() methods will return errors if the stream is disconnected.
|
||||
*
|
||||
* <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>
|
||||
*
|
||||
* We pass a shared_ptr so that the errorCallback object cannot be deleted before the stream is deleted.
|
||||
* If the stream was created using a shared_ptr then the stream cannot be deleted before the
|
||||
* error callback has finished running.
|
||||
*
|
||||
* @param sharedErrorCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setErrorCallback(std::shared_ptr<AudioStreamErrorCallback> sharedErrorCallback) {
|
||||
// Use this raw pointer in the rest of the code to retain backwards compatibility.
|
||||
mErrorCallback = sharedErrorCallback.get();
|
||||
// Hold a shared_ptr to protect the raw pointer for the lifetime of the stream.
|
||||
mSharedErrorCallback = sharedErrorCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass a raw pointer to an error callback. This is not recommended because the errorCallback
|
||||
* object might get deleted by the app while it is being used.
|
||||
*
|
||||
* @deprecated Call setErrorCallback(std::shared_ptr<AudioStreamErrorCallback>) instead.
|
||||
* @param errorCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setErrorCallback(AudioStreamErrorCallback *errorCallback) {
|
||||
mErrorCallback = errorCallback;
|
||||
mSharedErrorCallback = nullptr;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies an object to handle data presentation related callbacks from the underlying API.
|
||||
* This can occur when all data queued in the audio system for an offload stream has been
|
||||
* played.
|
||||
*
|
||||
* Note that presentation callbacks will only be called when a data callback has been specified
|
||||
* and the stream is started.
|
||||
*
|
||||
* <strong>Important: See AudioStreamCallback for restrictions on what may be called
|
||||
* from the callback methods.</strong>
|
||||
*
|
||||
* We pass a shared_ptr so that the presentationCallback object cannot be deleted before the
|
||||
* stream is deleted. If the stream was created using a shared_ptr then the stream cannot be
|
||||
* deleted before the presentation callback has finished running.
|
||||
*
|
||||
* @param sharedPresentationCallback
|
||||
* @return pointer to the builder so calls can be chained
|
||||
*/
|
||||
AudioStreamBuilder *setPresentationCallback(
|
||||
std::shared_ptr<AudioStreamPresentationCallback> sharedPresentationCallback) {
|
||||
mSharedPresentationCallback = sharedPresentationCallback;
|
||||
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>
|
||||
*
|
||||
* @deprecated Call setDataCallback(std::shared_ptr<AudioStreamDataCallback>) and
|
||||
* setErrorCallback(std::shared_ptr<AudioStreamErrorCallback>) instead.
|
||||
* @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 false.
|
||||
*/
|
||||
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::Medium
|
||||
*/
|
||||
AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) {
|
||||
mSampleRateConversionQuality = quality;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare the name of the package creating the stream.
|
||||
*
|
||||
* This is usually {@code Context#getPackageName()}.
|
||||
*
|
||||
* The default, if you do not call this function, is a random package in the calling uid.
|
||||
* The vast majority of apps have only one package per calling UID.
|
||||
* If an invalid package name is set, input streams may not be given permission to
|
||||
* record when started.
|
||||
*
|
||||
* The package name is usually the applicationId in your app's build.gradle file.
|
||||
*
|
||||
* Available since 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 {@code Context#getAttributionTag()}.
|
||||
*
|
||||
* The default, if you do not call this function, is null.
|
||||
*
|
||||
* Available since 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:
|
||||
|
||||
/**
|
||||
* Use this internally to implement opening with a shared_ptr.
|
||||
*
|
||||
* @param stream pointer to a variable to receive the stream address
|
||||
* @return OBOE_OK if successful or a negative error code.
|
||||
*/
|
||||
Result openStreamInternal(AudioStream **streamPP);
|
||||
|
||||
/**
|
||||
* @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_ */
|
215
externals/oboe/include/oboe/AudioStreamCallback.h
vendored
Normal file
215
externals/oboe/include/oboe/AudioStreamCallback.h
vendored
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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. If AudioStreamBuilder::setFramesPerCallback() is NOT called then
|
||||
* numFrames should always be <= AudioStream::getFramesPerBurst().
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Note: This callback is only fired when an AudioStreamCallback is set.
|
||||
* If you use AudioStream::write() you have to evaluate the return codes of
|
||||
* AudioStream::write() to notice errors in the stream.
|
||||
*
|
||||
* 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 */) {}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* AudioStreamPresentationCallback defines a callback interface for
|
||||
* being notified when a data presentation event is filed.
|
||||
*
|
||||
* It is used with AudioStreamBuilder::setPresentationCallback().
|
||||
*/
|
||||
class AudioStreamPresentationCallback {
|
||||
public:
|
||||
virtual ~AudioStreamPresentationCallback() = default;
|
||||
|
||||
/**
|
||||
* This will be called when all the buffers of an offloaded
|
||||
* stream that were queued in the audio system (e.g. the
|
||||
* combination of the Android audio framework and the device's
|
||||
* audio hardware) have been played.
|
||||
*
|
||||
* @param audioStream pointer to the associated stream
|
||||
*/
|
||||
virtual void onPresentationEnded(AudioStream* /* audioStream */) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
1140
externals/oboe/include/oboe/Definitions.h
vendored
Normal file
1140
externals/oboe/include/oboe/Definitions.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
164
externals/oboe/include/oboe/FifoBuffer.h
vendored
Normal file
164
externals/oboe/include/oboe/FifoBuffer.h
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* 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_FIFOPROCESSOR_H
|
||||
#define OBOE_FIFOPROCESSOR_H
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "oboe/Definitions.h"
|
||||
|
||||
#include "oboe/FifoControllerBase.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
class FifoBuffer {
|
||||
public:
|
||||
/**
|
||||
* Construct a `FifoBuffer`.
|
||||
*
|
||||
* @param bytesPerFrame amount of bytes for one frame
|
||||
* @param capacityInFrames the capacity of frames in fifo
|
||||
*/
|
||||
FifoBuffer(uint32_t bytesPerFrame, uint32_t capacityInFrames);
|
||||
|
||||
/**
|
||||
* Construct a `FifoBuffer`.
|
||||
* To be used if the storage allocation is done outside of FifoBuffer.
|
||||
*
|
||||
* @param bytesPerFrame amount of bytes for one frame
|
||||
* @param capacityInFrames capacity of frames in fifo
|
||||
* @param readCounterAddress address of read counter
|
||||
* @param writeCounterAddress address of write counter
|
||||
* @param dataStorageAddress address of storage
|
||||
*/
|
||||
FifoBuffer(uint32_t bytesPerFrame,
|
||||
uint32_t capacityInFrames,
|
||||
std::atomic<uint64_t> *readCounterAddress,
|
||||
std::atomic<uint64_t> *writeCounterAddress,
|
||||
uint8_t *dataStorageAddress);
|
||||
|
||||
~FifoBuffer();
|
||||
|
||||
/**
|
||||
* Convert a number of frames in bytes.
|
||||
*
|
||||
* @return number of bytes
|
||||
*/
|
||||
int32_t convertFramesToBytes(int32_t frames);
|
||||
|
||||
/**
|
||||
* Read framesToRead or, if not enough, then read as many as are available.
|
||||
*
|
||||
* @param destination
|
||||
* @param framesToRead number of frames requested
|
||||
* @return number of frames actually read
|
||||
*/
|
||||
int32_t read(void *destination, int32_t framesToRead);
|
||||
|
||||
/**
|
||||
* Write framesToWrite or, if too enough, then write as many as the fifo are not empty.
|
||||
*
|
||||
* @param destination
|
||||
* @param framesToWrite number of frames requested
|
||||
* @return number of frames actually write
|
||||
*/
|
||||
int32_t write(const void *source, int32_t framesToWrite);
|
||||
|
||||
/**
|
||||
* Get the buffer capacity in frames.
|
||||
*
|
||||
* @return number of frames
|
||||
*/
|
||||
uint32_t getBufferCapacityInFrames() const;
|
||||
|
||||
/**
|
||||
* Calls read(). If all of the frames cannot be read then the remainder of the buffer
|
||||
* is set to zero.
|
||||
*
|
||||
* @param destination
|
||||
* @param framesToRead number of frames requested
|
||||
* @return number of frames actually read
|
||||
*/
|
||||
int32_t readNow(void *destination, int32_t numFrames);
|
||||
|
||||
/**
|
||||
* Get the number of frames in the fifo.
|
||||
*
|
||||
* @return number of frames actually in the buffer
|
||||
*/
|
||||
uint32_t getFullFramesAvailable() {
|
||||
return mFifo->getFullFramesAvailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of bytes per frame.
|
||||
*
|
||||
* @return number of bytes per frame
|
||||
*/
|
||||
uint32_t getBytesPerFrame() const {
|
||||
return mBytesPerFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of read counter.
|
||||
*
|
||||
* @return position of read counter
|
||||
*/
|
||||
uint64_t getReadCounter() const {
|
||||
return mFifo->getReadCounter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of read counter.
|
||||
*
|
||||
* @param n position of read counter
|
||||
*/
|
||||
void setReadCounter(uint64_t n) {
|
||||
mFifo->setReadCounter(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of write counter.
|
||||
*
|
||||
* @return position of write counter
|
||||
*/
|
||||
uint64_t getWriteCounter() {
|
||||
return mFifo->getWriteCounter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of write counter.
|
||||
*
|
||||
* @param n position of write counter
|
||||
*/
|
||||
void setWriteCounter(uint64_t n) {
|
||||
mFifo->setWriteCounter(n);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mBytesPerFrame;
|
||||
uint8_t* mStorage;
|
||||
bool mStorageOwned; // did this object allocate the storage?
|
||||
std::unique_ptr<FifoControllerBase> mFifo;
|
||||
uint64_t mFramesReadCount;
|
||||
uint64_t mFramesUnderrunCount;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_FIFOPROCESSOR_H
|
112
externals/oboe/include/oboe/FifoControllerBase.h
vendored
Normal file
112
externals/oboe/include/oboe/FifoControllerBase.h
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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 NATIVEOBOE_FIFOCONTROLLERBASE_H
|
||||
#define NATIVEOBOE_FIFOCONTROLLERBASE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* Manage the read/write indices of a circular buffer.
|
||||
*
|
||||
* The caller is responsible for reading and writing the actual data.
|
||||
* Note that the span of available frames may not be contiguous. They
|
||||
* may wrap around from the end to the beginning of the buffer. In that
|
||||
* case the data must be read or written in at least two blocks of frames.
|
||||
*
|
||||
*/
|
||||
|
||||
class FifoControllerBase {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a `FifoControllerBase`.
|
||||
*
|
||||
* @param totalFrames capacity of the circular buffer in frames
|
||||
*/
|
||||
FifoControllerBase(uint32_t totalFrames);
|
||||
|
||||
virtual ~FifoControllerBase() = default;
|
||||
|
||||
/**
|
||||
* The frames available to read will be calculated from the read and write counters.
|
||||
* The result will be clipped to the capacity of the buffer.
|
||||
* If the buffer has underflowed then this will return zero.
|
||||
*
|
||||
* @return number of valid frames available to read.
|
||||
*/
|
||||
uint32_t getFullFramesAvailable() const;
|
||||
|
||||
/**
|
||||
* The index in a circular buffer of the next frame to read.
|
||||
*
|
||||
* @return read index position
|
||||
*/
|
||||
uint32_t getReadIndex() const;
|
||||
|
||||
/**
|
||||
* Advance read index from a number of frames.
|
||||
* Equivalent of incrementReadCounter(numFrames).
|
||||
*
|
||||
* @param numFrames number of frames to advance the read index
|
||||
*/
|
||||
void advanceReadIndex(uint32_t numFrames);
|
||||
|
||||
/**
|
||||
* Get the number of frame that are not written yet.
|
||||
*
|
||||
* @return maximum number of frames that can be written without exceeding the threshold
|
||||
*/
|
||||
uint32_t getEmptyFramesAvailable() const;
|
||||
|
||||
/**
|
||||
* The index in a circular buffer of the next frame to write.
|
||||
*
|
||||
* @return index of the next frame to write
|
||||
*/
|
||||
uint32_t getWriteIndex() const;
|
||||
|
||||
/**
|
||||
* Advance write index from a number of frames.
|
||||
* Equivalent of incrementWriteCounter(numFrames).
|
||||
*
|
||||
* @param numFrames number of frames to advance the write index
|
||||
*/
|
||||
void advanceWriteIndex(uint32_t numFrames);
|
||||
|
||||
/**
|
||||
* Get the frame capacity of the fifo.
|
||||
*
|
||||
* @return frame capacity
|
||||
*/
|
||||
uint32_t getFrameCapacity() const { return mTotalFrames; }
|
||||
|
||||
virtual uint64_t getReadCounter() const = 0;
|
||||
virtual void setReadCounter(uint64_t n) = 0;
|
||||
virtual void incrementReadCounter(uint64_t n) = 0;
|
||||
virtual uint64_t getWriteCounter() const = 0;
|
||||
virtual void setWriteCounter(uint64_t n) = 0;
|
||||
virtual void incrementWriteCounter(uint64_t n) = 0;
|
||||
|
||||
private:
|
||||
uint32_t mTotalFrames;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //NATIVEOBOE_FIFOCONTROLLERBASE_H
|
356
externals/oboe/include/oboe/FullDuplexStream.h
vendored
Normal file
356
externals/oboe/include/oboe/FullDuplexStream.h
vendored
Normal file
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OBOE_FULL_DUPLEX_STREAM_
|
||||
#define OBOE_FULL_DUPLEX_STREAM_
|
||||
|
||||
#include <cstdint>
|
||||
#include "oboe/Definitions.h"
|
||||
#include "oboe/AudioStream.h"
|
||||
#include "oboe/AudioStreamCallback.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* FullDuplexStream can be used to synchronize an input and output stream.
|
||||
*
|
||||
* For the builder of the output stream, call setDataCallback() with this object.
|
||||
*
|
||||
* When both streams are ready, onAudioReady() of the output stream will call onBothStreamsReady().
|
||||
* Callers must override onBothStreamsReady().
|
||||
*
|
||||
* To ensure best results, open an output stream before the input stream.
|
||||
* Call inputBuilder.setBufferCapacityInFrames(mOutputStream->getBufferCapacityInFrames() * 2).
|
||||
* Also, call inputBuilder.setSampleRate(mOutputStream->getSampleRate()).
|
||||
*
|
||||
* Callers must call setInputStream() and setOutputStream().
|
||||
* Call start() to start both streams and stop() to stop both streams.
|
||||
* Caller is responsible for closing both streams.
|
||||
*
|
||||
* Callers should handle error callbacks with setErrorCallback() for the output stream.
|
||||
* When an error callback occurs for the output stream, Oboe will stop and close the output stream.
|
||||
* The caller is responsible for stopping and closing the input stream.
|
||||
* The caller should also reopen and restart both streams when the error callback is ErrorDisconnected.
|
||||
* See the LiveEffect sample as an example of this.
|
||||
*
|
||||
*/
|
||||
class FullDuplexStream : public AudioStreamDataCallback {
|
||||
public:
|
||||
FullDuplexStream() {}
|
||||
virtual ~FullDuplexStream() = default;
|
||||
|
||||
/**
|
||||
* Sets the input stream.
|
||||
*
|
||||
* @deprecated Call setSharedInputStream(std::shared_ptr<AudioStream> &stream) instead.
|
||||
* @param stream the output stream
|
||||
*/
|
||||
void setInputStream(AudioStream *stream) {
|
||||
mRawInputStream = stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the input stream. Calling this is mandatory.
|
||||
*
|
||||
* @param stream the output stream
|
||||
*/
|
||||
void setSharedInputStream(std::shared_ptr<AudioStream> &stream) {
|
||||
mSharedInputStream = stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current input stream. This function tries to return the shared input stream if it
|
||||
* is set before the raw input stream.
|
||||
*
|
||||
* @return pointer to an output stream or nullptr.
|
||||
*/
|
||||
AudioStream *getInputStream() {
|
||||
if (mSharedInputStream) {
|
||||
return mSharedInputStream.get();
|
||||
} else {
|
||||
return mRawInputStream;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output stream.
|
||||
*
|
||||
* @deprecated Call setSharedOutputStream(std::shared_ptr<AudioStream> &stream) instead.
|
||||
* @param stream the output stream
|
||||
*/
|
||||
void setOutputStream(AudioStream *stream) {
|
||||
mRawOutputStream = stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output stream. Calling this is mandatory.
|
||||
*
|
||||
* @param stream the output stream
|
||||
*/
|
||||
void setSharedOutputStream(std::shared_ptr<AudioStream> &stream) {
|
||||
mSharedOutputStream = stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current output stream. This function tries to return the shared output stream if it
|
||||
* is set before the raw output stream.
|
||||
*
|
||||
* @return pointer to an output stream or nullptr.
|
||||
*/
|
||||
AudioStream *getOutputStream() {
|
||||
if (mSharedOutputStream) {
|
||||
return mSharedOutputStream.get();
|
||||
} else {
|
||||
return mRawOutputStream;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to start both streams. Please call setInputStream() and setOutputStream() before
|
||||
* calling this function.
|
||||
*
|
||||
* @return result of the operation
|
||||
*/
|
||||
virtual Result start() {
|
||||
mCountCallbacksToDrain = kNumCallbacksToDrain;
|
||||
mCountInputBurstsCushion = mNumInputBurstsCushion;
|
||||
mCountCallbacksToDiscard = kNumCallbacksToDiscard;
|
||||
|
||||
// Determine maximum size that could possibly be called.
|
||||
int32_t bufferSize = getOutputStream()->getBufferCapacityInFrames()
|
||||
* getOutputStream()->getChannelCount();
|
||||
if (bufferSize > mBufferSize) {
|
||||
mInputBuffer = std::make_unique<float[]>(bufferSize);
|
||||
mBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
oboe::Result result = getInputStream()->requestStart();
|
||||
if (result != oboe::Result::OK) {
|
||||
return result;
|
||||
}
|
||||
return getOutputStream()->requestStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops both streams. Returns Result::OK if neither stream had an error during close.
|
||||
*
|
||||
* @return result of the operation
|
||||
*/
|
||||
virtual Result stop() {
|
||||
Result outputResult = Result::OK;
|
||||
Result inputResult = Result::OK;
|
||||
if (getOutputStream()) {
|
||||
outputResult = getOutputStream()->requestStop();
|
||||
}
|
||||
if (getInputStream()) {
|
||||
inputResult = getOutputStream()->requestStop();
|
||||
}
|
||||
if (outputResult != Result::OK) {
|
||||
return outputResult;
|
||||
} else {
|
||||
return inputResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads input from the input stream. Callers should not call this directly as this is called
|
||||
* in onAudioReady().
|
||||
*
|
||||
* @param numFrames
|
||||
* @return result of the operation
|
||||
*/
|
||||
virtual ResultWithValue<int32_t> readInput(int32_t numFrames) {
|
||||
return getInputStream()->read(mInputBuffer.get(), numFrames, 0 /* timeout */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when data is available on both streams.
|
||||
* Caller should override this method.
|
||||
* numInputFrames and numOutputFrames may be zero.
|
||||
*
|
||||
* @param inputData buffer containing input data
|
||||
* @param numInputFrames number of input frames
|
||||
* @param outputData a place to put output data
|
||||
* @param numOutputFrames number of output frames
|
||||
* @return DataCallbackResult::Continue or DataCallbackResult::Stop
|
||||
*/
|
||||
virtual DataCallbackResult onBothStreamsReady(
|
||||
const void *inputData,
|
||||
int numInputFrames,
|
||||
void *outputData,
|
||||
int numOutputFrames
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Called when the output stream is ready to process audio.
|
||||
* This in return calls onBothStreamsReady() when data is available on both streams.
|
||||
* Callers should call this function when the output stream is ready.
|
||||
* Callers must override onBothStreamsReady().
|
||||
*
|
||||
* @param audioStream pointer to the associated stream
|
||||
* @param audioData a place to put output data
|
||||
* @param numFrames number of frames to be processed
|
||||
* @return DataCallbackResult::Continue or DataCallbackResult::Stop
|
||||
*
|
||||
*/
|
||||
DataCallbackResult onAudioReady(
|
||||
AudioStream * /*audioStream*/,
|
||||
void *audioData,
|
||||
int numFrames) {
|
||||
DataCallbackResult callbackResult = DataCallbackResult::Continue;
|
||||
int32_t actualFramesRead = 0;
|
||||
|
||||
// Silence the output.
|
||||
int32_t numBytes = numFrames * getOutputStream()->getBytesPerFrame();
|
||||
memset(audioData, 0 /* value */, numBytes);
|
||||
|
||||
if (mCountCallbacksToDrain > 0) {
|
||||
// Drain the input.
|
||||
int32_t totalFramesRead = 0;
|
||||
do {
|
||||
ResultWithValue<int32_t> result = readInput(numFrames);
|
||||
if (!result) {
|
||||
// Ignore errors because input stream may not be started yet.
|
||||
break;
|
||||
}
|
||||
actualFramesRead = result.value();
|
||||
totalFramesRead += actualFramesRead;
|
||||
} while (actualFramesRead > 0);
|
||||
// Only counts if we actually got some data.
|
||||
if (totalFramesRead > 0) {
|
||||
mCountCallbacksToDrain--;
|
||||
}
|
||||
|
||||
} else if (mCountInputBurstsCushion > 0) {
|
||||
// Let the input fill up a bit so we are not so close to the write pointer.
|
||||
mCountInputBurstsCushion--;
|
||||
|
||||
} else if (mCountCallbacksToDiscard > 0) {
|
||||
mCountCallbacksToDiscard--;
|
||||
// Ignore. Allow the input to reach to equilibrium with the output.
|
||||
ResultWithValue<int32_t> resultAvailable = getInputStream()->getAvailableFrames();
|
||||
if (!resultAvailable) {
|
||||
callbackResult = DataCallbackResult::Stop;
|
||||
} else {
|
||||
int32_t framesAvailable = resultAvailable.value();
|
||||
if (framesAvailable >= mMinimumFramesBeforeRead) {
|
||||
ResultWithValue<int32_t> resultRead = readInput(numFrames);
|
||||
if (!resultRead) {
|
||||
callbackResult = DataCallbackResult::Stop;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int32_t framesRead = 0;
|
||||
ResultWithValue<int32_t> resultAvailable = getInputStream()->getAvailableFrames();
|
||||
if (!resultAvailable) {
|
||||
callbackResult = DataCallbackResult::Stop;
|
||||
} else {
|
||||
int32_t framesAvailable = resultAvailable.value();
|
||||
if (framesAvailable >= mMinimumFramesBeforeRead) {
|
||||
// Read data into input buffer.
|
||||
ResultWithValue<int32_t> resultRead = readInput(numFrames);
|
||||
if (!resultRead) {
|
||||
callbackResult = DataCallbackResult::Stop;
|
||||
} else {
|
||||
framesRead = resultRead.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callbackResult == DataCallbackResult::Continue) {
|
||||
callbackResult = onBothStreamsReady(mInputBuffer.get(), framesRead,
|
||||
audioData, numFrames);
|
||||
}
|
||||
}
|
||||
|
||||
if (callbackResult == DataCallbackResult::Stop) {
|
||||
getInputStream()->requestStop();
|
||||
}
|
||||
|
||||
return callbackResult;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This is a cushion between the DSP and the application processor cursors to prevent collisions.
|
||||
* Typically 0 for latency measurements or 1 for glitch tests.
|
||||
*
|
||||
* @param numBursts number of bursts to leave in the input buffer as a cushion
|
||||
*/
|
||||
void setNumInputBurstsCushion(int32_t numBursts) {
|
||||
mNumInputBurstsCushion = numBursts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bursts left in the input buffer as a cushion.
|
||||
*
|
||||
* @return number of bursts in the input buffer as a cushion
|
||||
*/
|
||||
int32_t getNumInputBurstsCushion() const {
|
||||
return mNumInputBurstsCushion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimum number of frames in the input stream buffer before calling readInput().
|
||||
*
|
||||
* @param numFrames number of bursts in the input buffer as a cushion
|
||||
*/
|
||||
void setMinimumFramesBeforeRead(int32_t numFrames) {
|
||||
mMinimumFramesBeforeRead = numFrames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum number of frames in the input stream buffer before calling readInput().
|
||||
*
|
||||
* @return minimum number of frames before reading
|
||||
*/
|
||||
int32_t getMinimumFramesBeforeRead() const {
|
||||
return mMinimumFramesBeforeRead;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// TODO add getters and setters
|
||||
static constexpr int32_t kNumCallbacksToDrain = 20;
|
||||
static constexpr int32_t kNumCallbacksToDiscard = 30;
|
||||
|
||||
// let input fill back up, usually 0 or 1
|
||||
int32_t mNumInputBurstsCushion = 0;
|
||||
int32_t mMinimumFramesBeforeRead = 0;
|
||||
|
||||
// We want to reach a state where the input buffer is empty and
|
||||
// the output buffer is full.
|
||||
// These are used in order.
|
||||
// Drain several callback so that input is empty.
|
||||
int32_t mCountCallbacksToDrain = kNumCallbacksToDrain;
|
||||
// Let the input fill back up slightly so we don't run dry.
|
||||
int32_t mCountInputBurstsCushion = mNumInputBurstsCushion;
|
||||
// Discard some callbacks so the input and output reach equilibrium.
|
||||
int32_t mCountCallbacksToDiscard = kNumCallbacksToDiscard;
|
||||
|
||||
AudioStream *mRawInputStream = nullptr;
|
||||
AudioStream *mRawOutputStream = nullptr;
|
||||
std::shared_ptr<AudioStream> mSharedInputStream;
|
||||
std::shared_ptr<AudioStream> mSharedOutputStream;
|
||||
|
||||
int32_t mBufferSize = 0;
|
||||
std::unique_ptr<float[]> mInputBuffer;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_FULL_DUPLEX_STREAM_
|
150
externals/oboe/include/oboe/LatencyTuner.h
vendored
Normal file
150
externals/oboe/include/oboe/LatencyTuner.h
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* 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_
|
44
externals/oboe/include/oboe/Oboe.h
vendored
Normal file
44
externals/oboe/include/oboe/Oboe.h
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* See our <a href="https://github.com/google/oboe/blob/main/docs/FullGuide.md">guide</a> on Github
|
||||
* for a guide on Oboe.
|
||||
*
|
||||
* Click the classes tab to see the reference for various Oboe functions.
|
||||
*
|
||||
*/
|
||||
|
||||
#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"
|
||||
#include "oboe/FifoBuffer.h"
|
||||
#include "oboe/OboeExtensions.h"
|
||||
#include "oboe/FullDuplexStream.h"
|
||||
#include "oboe/AudioClock.h"
|
||||
|
||||
#endif //OBOE_OBOE_H
|
64
externals/oboe/include/oboe/OboeExtensions.h
vendored
Normal file
64
externals/oboe/include/oboe/OboeExtensions.h
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2022 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_EXTENSIONS_
|
||||
#define OBOE_EXTENSIONS_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "oboe/Definitions.h"
|
||||
#include "oboe/AudioStream.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
* The definitions below are only for testing.
|
||||
* They are not recommended for use in an application.
|
||||
* They may change or be removed at any time.
|
||||
*/
|
||||
class OboeExtensions {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @returns true if the device supports AAudio MMAP
|
||||
*/
|
||||
static bool isMMapSupported();
|
||||
|
||||
/**
|
||||
* @returns true if the AAudio MMAP data path can be selected
|
||||
*/
|
||||
static bool isMMapEnabled();
|
||||
|
||||
/**
|
||||
* Controls whether the AAudio MMAP data path can be selected when opening a stream.
|
||||
* It has no effect after the stream has been opened.
|
||||
* It only affects the application that calls it. Other apps are not affected.
|
||||
*
|
||||
* @param enabled
|
||||
* @return 0 or a negative error code
|
||||
*/
|
||||
static int32_t setMMapEnabled(bool enabled);
|
||||
|
||||
/**
|
||||
* @param oboeStream
|
||||
* @return true if the AAudio MMAP data path is used on the stream
|
||||
*/
|
||||
static bool isMMapUsed(oboe::AudioStream *oboeStream);
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif // OBOE_LATENCY_TUNER_
|
155
externals/oboe/include/oboe/ResultWithValue.h
vendored
Normal file
155
externals/oboe/include/oboe/ResultWithValue.h
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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
|
75
externals/oboe/include/oboe/StabilizedCallback.h
vendored
Normal file
75
externals/oboe/include/oboe/StabilizedCallback.h
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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__) || defined(__riscv)
|
||||
#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
|
101
externals/oboe/include/oboe/Utilities.h
vendored
Normal file
101
externals/oboe/include/oboe/Utilities.h
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* Returns whether a device is on a pre-release SDK that is at least the specified codename
|
||||
* version.
|
||||
*
|
||||
* @param codename the code name to verify.
|
||||
* @return boolean of whether the device is on a pre-release SDK and is at least the specified
|
||||
* codename
|
||||
*/
|
||||
bool isAtLeastPreReleaseCodename(const std::string& codename);
|
||||
|
||||
int getChannelCountFromChannelMask(ChannelMask channelMask);
|
||||
|
||||
bool isCompressedFormat(AudioFormat format);
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_UTILITIES_H
|
92
externals/oboe/include/oboe/Version.h
vendored
Normal file
92
externals/oboe/include/oboe/Version.h
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 9
|
||||
|
||||
// Type: 16-bit unsigned int. Min value: 0 Max value: 65535. See below for description.
|
||||
#define OBOE_VERSION_PATCH 4
|
||||
|
||||
#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
|
Loading…
Add table
Add a link
Reference in a new issue