Skip to content

Commit

Permalink
Use oboe namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
dturner committed Feb 12, 2018
1 parent 2140eb1 commit f7b9295
Show file tree
Hide file tree
Showing 40 changed files with 1,041 additions and 910 deletions.
33 changes: 31 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,37 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -std=c++11")
# Specify directories which the compiler should look for headers
include_directories(
include
src)
src
/Users/donturner/Library/Android/sdk/ndk-bundle/sysroot/usr/include
/Users/donturner/Library/Android/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi/
)

#file(GLOB_RECURSE oboe_sources src/*)

set (oboe_sources
include/oboe/LatencyTuner.h
include/oboe/Definitions.h
include/oboe/Stream.h
include/oboe/StreamBase.h
include/oboe/StreamBuilder.h
include/oboe/StreamCallback.h
include/oboe/Utilities.h
src/aaudio/AAudioLoader.cpp
src/aaudio/StreamAAudio.cpp
src/common/AudioClock.h
src/common/OboeDebug.h
src/common/LatencyTuner.cpp
src/common/Stream.cpp
src/common/StreamBuilder.cpp
src/common/Utilities.cpp
src/fifo/FifoBuffer.cpp
src/fifo/FifoController.cpp
src/fifo/FifoControllerBase.cpp
src/fifo/FifoControllerIndirect.cpp
src/opensles/StreamBuffered.cpp
src/opensles/StreamOpenSLES.cpp
src/opensles/OpenSLESUtilities.cpp
)

file(GLOB_RECURSE oboe_sources src/*)

add_library(oboe STATIC ${oboe_sources})
66 changes: 33 additions & 33 deletions FullGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Oboe is a C++ library which makes it easy to build high-performance audio apps o

## Audio streams

Oboe moves audio data between your app and the audio inputs and outputs on your Android device. Your app passes data in and out by reading from and writing to *audio streams*, represented by the class `OboeStream`. The read/write calls can be blocking or non-blocking.
Oboe moves audio data between your app and the audio inputs and outputs on your Android device. Your app passes data in and out by reading from and writing to *audio streams*, represented by the class `Stream`. The read/write calls can be blocking or non-blocking.

A stream is defined by the following:

Expand Down Expand Up @@ -59,11 +59,11 @@ Oboe might perform sample conversion on its own. For example, if an app is writi

## Creating an audio stream

The Oboe library follows a [builder design pattern](https://en.wikipedia.org/wiki/Builder_pattern) and provides the class `OboeStreamBuilder`.
The Oboe library follows a [builder design pattern](https://en.wikipedia.org/wiki/Builder_pattern) and provides the class `StreamBuilder`.

1. Set the audio stream configuration using an OboeStreamBuilder. Use the builder functions that correspond to the stream parameters. These optional set functions are available:
1. Set the audio stream configuration using an StreamBuilder. Use the builder functions that correspond to the stream parameters. These optional set functions are available:

OboeStreamBuilder streamBuilder;
StreamBuilder streamBuilder;

streamBuilder.setDeviceId(deviceId);
streamBuilder.setDirection(direction);
Expand All @@ -81,8 +81,8 @@ whether Oboe will use AAudio or OpenSL ES as the audio engine for you app. Oboe
will automatically select the best implementation available on your device. If
you want to specifically select AAudio or OpenSL, set the APIIndex yourself.
After a stream has been opened, you can verify that the API you specified was
chosen by calling `OboeStreamBuilder::getAPIIndex()`. The allowable indexes are
`API_AAUDIO` and `API_OPENSL_ES`.
chosen by calling `StreamBuilder::getAPIIndex()`. The allowable indexes are
`AAudio` and `OpenSLES`.

If you do not specify the deviceId, the default is the primary output device.
If you do not specify the stream direction, the default is an output stream.
Expand All @@ -92,10 +92,10 @@ it to `OBOE_UNSPECIFIED`.

To be safe, check the state of the audio stream after you create it, as explained in step 3, below.

2. After you've configured the OboeStreamBuilder, call `openStream()` to open the stream:
2. After you've configured the StreamBuilder, call `openStream()` to open the stream:

oboe_result_t result = streamBuilder.openStream(&stream_);
if (result != OBOE_OK){
Result result = streamBuilder.openStream(&stream_);
if (result != OK){
__android_log_print(ANDROID_LOG_ERROR,
"AudioEngine",
"Error opening stream %s",
Expand Down Expand Up @@ -139,7 +139,7 @@ Data only flows through a stream when the stream is in the Started state. To
move a stream between states, use one of the functions that request a state
transition:

oboe_result_t result;
Result result;
result = stream->requestStart();
result = stream->requestStop();
result = stream->requestPause();
Expand All @@ -166,7 +166,7 @@ Though it's not shown, you can call `close()` from any state

Oboe doesn't provide callbacks to alert you to state changes. One special
function,
`OboeStream::waitForStateChange()` can be used to wait for a state change.
`Stream::waitForStateChange()` can be used to wait for a state change.

The function does not detect a state change on its own, and does not wait for a
specific state. It waits until the current state
Expand All @@ -178,8 +178,8 @@ Since you can't wait for the Paused state, use `waitForStateChange()` to wait fo
other than Pausing*. Here's how that's done:

```
oboe_stream_state_t inputState = OBOE_STREAM_STATE_PAUSING;
oboe_stream_state_t nextState = OBOE_STREAM_STATE_UNINITIALIZED;
StreamState inputState = OBOE_STREAM_STATE_PAUSING;
StreamState nextState = OBOE_STREAM_STATE_UNINITIALIZED;
int64_t timeoutNanos = 100 * OBOE_NANOS_PER_MILLISECOND;
result = stream->requestPause();
result = stream->waitForStateChange(inputState, &nextState, timeoutNanos);
Expand All @@ -194,16 +194,16 @@ stream.

You can use this same technique after calling request start, stop, or flush,
using the corresponding transient state as the inputState. Do not call
`waitForStateChange()` after calling `OboeStream::close()` since the stream
`waitForStateChange()` after calling `Stream::close()` since the stream
will be deleted as soon as it closes. And do not call `close()`
while `waitForStateChange()` is running in another thread.

### Reading and writing to an audio stream

After the stream is started you can read or write to it using the methods
`OboeStream::read(buffer, numFrames, timeoutNanos)`
`Stream::read(buffer, numFrames, timeoutNanos)`
and
`OboeStream::write(buffer, numFrames, timeoutNanos)`.
`Stream::write(buffer, numFrames, timeoutNanos)`.


For a blocking read or write that transfers the specified number of frames, set timeoutNanos greater than zero. For a non-blocking call, set timeoutNanos to zero. In this case the result is the actual number of frames transferred.
Expand All @@ -214,7 +214,7 @@ frames was read. If not, the buffer might contain unknown data that could cause
audio glitch. You can pad the buffer with zeros to create a
silent dropout:

oboe_result_t result =
Result result =
stream.read(audioData, numFrames, timeout);
if (result < 0) {
// Error!
Expand Down Expand Up @@ -248,7 +248,7 @@ An audio stream can become disconnected at any time if one of these events happe
When a stream is disconnected, it has the state "Disconnected" and any attempts to execute write() or other functions return `OBOE_ERROR_DISCONNECTED`. When a stream is disconnected, all you can do is close it.

If you need to be informed when an audio device is disconnected, write a class
which extends `OboeStreamCallback` and implements the `onError(stream, error)`
which extends `StreamCallback` and implements the `onError(stream, error)`
method. Register your class using `builder.setCallback(yourCallbackClass)`.

The `onError()` method should check the state of the stream as shown in the following
Expand All @@ -258,7 +258,7 @@ stream it might have different characteristics than the
original stream (for example framesPerBurst):

```
void PlayAudioEngine::onError(OboeStream *audioStream, oboe_result_t error) {
void PlayAudioEngine::onError(Stream *audioStream, Result error) {
if (error == OBOE_ERROR_DISCONNECTED) {
// Handle stream restart on a separate thread
std::function<void(void)> restartStream = std::bind(&PlayAudioEngine::restartStream, this);
Expand All @@ -268,7 +268,7 @@ void PlayAudioEngine::onError(OboeStream *audioStream, oboe_result_t error) {
}
```

You can also implement two other callback methods in the class `OboeStreamCallback`:
You can also implement two other callback methods in the class `StreamCallback`:

* `onAudioReady()` is used for a high-priority callback
* `onExit()` is called when the callback thread exits.
Expand All @@ -285,13 +285,13 @@ For applications that require low latency, an audio stream can use an asynchrono
The callback runs in a high-priority thread that has better performance.

Your code can access the callback mechanism by implementing the virtual class
`OboeStreamCallback`. The stream periodically executes `onAudioReady()` (the
`StreamCallback`. The stream periodically executes `onAudioReady()` (the
callback function) to acquire the data for its next burst.

class AudioEngine : OboeStreamCallback {
class AudioEngine : StreamCallback {
public:
oboe_data_callback_result_t AudioEngine::onAudioReady(
OboeStream *oboeStream,
Stream *oboeStream,
void *audioData,
int32_t numFrames){
oscillator_->render(static_cast<float *>(audioData), numFrames);
Expand Down Expand Up @@ -322,14 +322,14 @@ The callback does a non-blocking read from the input stream placing the data int

(Note that Oboe version 1 does not support input streams, so this example cannot run.)

class AudioEngine : OboeStreamCallback {
class AudioEngine : StreamCallback {
public:

oboe_data_callback_result_t AudioEngine::onAudioReady(
OboeStream *oboeStream,
Stream *oboeStream,
void *audioData,
int32_t numFrames){
oboe_result_t result =
Result result =
stream2.read(audioData, numFrames, timeout);

if (result == numFrames)
Expand All @@ -347,20 +347,20 @@ The callback does a non-blocking read from the input stream placing the data int
streamBuilder.setCallback(this);
}

void setRecordingStream(OboeStream *stream) {
void setRecordingStream(Stream *stream) {
recordingStream = stream;
}

private:
OboeStream *recordingStream;
Stream *recordingStream;
}


Note that in this example it is assumed the input and output streams have the same number of channels, format and sample rate. The format of the streams can be mismatched - as long as the code handles the translations properly.

### Setting performance mode

Every OboeStream has a *performance mode* which has a large effect on your app's behavior. There are three modes:
Every Stream has a *performance mode* which has a large effect on your app's behavior. There are three modes:

* `OBOE_PERFORMANCE_MODE_NONE` is the default mode. It uses a basic stream that balances latency and power savings.
* `OBOE_PERFORMANCE_MODE_LOW_LATENCY` uses smaller buffers and an optimized data path for reduced latency.
Expand All @@ -382,12 +382,12 @@ In the current version of Oboe, in order to achieve the lowest possible latency
MyOboeStreamCallback myCallback;
// Create a stream builder
OboeStreamBuilder builder;
StreamBuilder builder;
builder.setCallback(myCallback);
builder.setPerformanceMode(OBOE_PERFORMANCE_MODE_LOW_LATENCY);
// Use it to create the stream
OboeStream *stream;
Stream *stream;
builder.openStream(&stream);
```

Expand All @@ -399,7 +399,7 @@ This is because Oboe avoids using mutexes, which can cause thread preemption and

To be safe, don't call `waitForStateChange()` or read or write to the same stream from two different threads. Similarly, don't close a stream in one thread while reading or writing to it in another thread.

Calls that return stream settings, like `OboeStream::getSampleRate()` and `OboeStream::getChannelCount()`, are thread safe.
Calls that return stream settings, like `Stream::getSampleRate()` and `Stream::getChannelCount()`, are thread safe.

These calls are also thread safe:

Expand All @@ -409,7 +409,7 @@ These calls are also thread safe:
* `Oboe_convertSharingModeToText()`
* `Oboe_convertDataCallbackResultToText()`
* `Oboe_convertDirectionToText()`
* `OboeStream::get*()` except for `getTimestamp()`
* `Stream::get*()` except for `getTimestamp()`


<b>Note:</b> When a stream uses a callback function, it's safe to read/write from the callback thread while also closing the stream
Expand Down
18 changes: 9 additions & 9 deletions GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,22 @@ Include the Oboe header:

#include <oboe/Oboe.h>

Streams are built using an `OboeStreamBuilder`. Create one like this:
Streams are built using an `StreamBuilder`. Create one like this:

OboeStreamBuilder builder;
StreamBuilder builder;

Use the builder's set methods to set properties on the stream (you can read more about these properties in the [full guide](FullGuide.md)):

builder.setDirection(OBOE_DIRECTION_OUTPUT);
builder.setPerformanceMode(OBOE_PERFORMANCE_MODE_LOW_LATENCY);
builder.setSharingMode(OBOE_SHARING_MODE_EXCLUSIVE);

Define an `OboeStreamCallback` class to receive callbacks whenever the stream requires new data.
Define an `StreamCallback` class to receive callbacks whenever the stream requires new data.

class MyCallback : public OboeStreamCallback {
class MyCallback : public StreamCallback {
public:
oboe_data_callback_result_t
onAudioReady(OboeStream *audioStream, void *audioData, int32_t numFrames){
onAudioReady(Stream *audioStream, void *audioData, int32_t numFrames){
generateSineWave(static_cast<float *>(audioData), numFrames);
return OBOE_CALLBACK_RESULT_CONTINUE;
}
Expand All @@ -76,18 +76,18 @@ Supply this callback class to the builder:

Open the stream:

OboeStream *stream;
oboe_result_t result = builder.openStream(&stream);
Stream *stream;
Result result = builder.openStream(&stream);

Check the result to make sure the stream was opened successfully. Oboe has many convenience methods for converting its types into human-readable strings, they all start with `Oboe_convert`:

if (result != OBOE_OK){
if (result != OK){
LOGE("Failed to create stream. Error: %s", Oboe_convertResultToText(result));
}

Note that this sample code uses the [logging macros from here](https://github.com/googlesamples/android-audio-high-performance/blob/master/debug-utils/logging_macros.h).

Check the properties of the created stream. The **format** is one property which you should check. The default is `float` on API 21+ and `int16_t` on API 20 or lower. This will dictate the `audioData` type in the `OboeStreamCallback::onAudioReady` callback.
Check the properties of the created stream. The **format** is one property which you should check. The default is `float` on API 21+ and `int16_t` on API 20 or lower. This will dictate the `audioData` type in the `StreamCallback::onAudioReady` callback.

oboe_audio_format_t format = stream->getFormat();
LOGI("Stream format is %s", Oboe_convertAudioFormatToText(format));
Expand Down
4 changes: 2 additions & 2 deletions build_all_android.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ build_oboe x86_64 21
printf "%s\r\n" "example: |" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " #include <oboe/Oboe.h>" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " void openStream() {" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " OboeStreamBuilder builder;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " OboeStream *stream;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " StreamBuilder builder;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " Stream *stream;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " builder.openStream(&stream);" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " }" >> ${CDEP_MANIFEST_FILE}

Expand Down
Loading

0 comments on commit f7b9295

Please sign in to comment.