Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New namespace, constexprs and scoped enums #18

Merged
merged 11 commits into from
Dec 1, 2017
18 changes: 9 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,25 @@ include_directories(
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/AudioStream.h
include/oboe/AudioStreamBase.h
include/oboe/AudioStreamBuilder.h
include/oboe/AudioStreamCallback.h
include/oboe/Utilities.h
src/aaudio/AAudioLoader.cpp
src/aaudio/StreamAAudio.cpp
src/aaudio/AudioStreamAAudio.cpp
src/common/AudioClock.h
src/common/OboeDebug.h
src/common/LatencyTuner.cpp
src/common/Stream.cpp
src/common/StreamBuilder.cpp
src/common/AudioStream.cpp
src/common/AudioStreamBuilder.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/AudioStreamBuffered.cpp
src/opensles/AudioStreamOpenSLES.cpp
src/opensles/OpenSLESUtilities.cpp
)

Expand Down
52 changes: 26 additions & 26 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 `Stream`. 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 `AudioStream`. 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 `StreamBuilder`.
The Oboe library follows a [builder design pattern](https://en.wikipedia.org/wiki/Builder_pattern) and provides the class `AudioStreamBuilder`.

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:
1. Set the audio stream configuration using an AudioStreamBuilder. Use the builder functions that correspond to the stream parameters. These optional set functions are available:

StreamBuilder streamBuilder;
AudioStreamBuilder streamBuilder;

streamBuilder.setDeviceId(deviceId);
streamBuilder.setDirection(direction);
Expand All @@ -81,7 +81,7 @@ 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 `StreamBuilder::getAPIIndex()`. The allowable indexes are
chosen by calling `AudioStreamBuilder::getAPIIndex()`. The allowable indexes are
`AAudio` and `OpenSLES`.

If you do not specify the deviceId, the default is the primary output device.
Expand All @@ -92,7 +92,7 @@ it to `kUnspecified`.

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 StreamBuilder, call `openStream()` to open the stream:
2. After you've configured the AudioStreamBuilder, call `openStream()` to open the stream:

Result result = streamBuilder.openStream(&stream_);
if (result != OK){
Expand All @@ -113,7 +113,7 @@ To be safe, check the state of the audio stream after you create it, as explaine
builder setting:


| StreamBuilder set methods | Stream get methods |
| AudioStreamBuilder set methods | AudioStream get methods |
| :------------------------ | :----------------- |
| `setDeviceId()` | `getDeviceId()` |
| `setDirection()` | `getDirection()` |
Expand Down Expand Up @@ -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,
`Stream::waitForStateChange()` can be used to wait for a state change.
`AudioStream::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 Down Expand Up @@ -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 `Stream::close()` since the stream
`waitForStateChange()` after calling `AudioStream::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
`Stream::read(buffer, numFrames, timeoutNanos)`
`AudioStream::read(buffer, numFrames, timeoutNanos)`
and
`Stream::write(buffer, numFrames, timeoutNanos)`.
`AudioStream::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 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 `StreamCallback` and implements the `onError(stream, error)`
which extends `AudioStreamCallback` 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(Stream *audioStream, Result error) {
void PlayAudioEngine::onError(AudioStream *audioStream, Result error) {
if (error == Result::ErrorDisconnected) {
// 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(Stream *audioStream, Result error) {
}
```

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

* `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
`StreamCallback`. The stream periodically executes `onAudioReady()` (the
`AudioStreamCallback`. The stream periodically executes `onAudioReady()` (the
callback function) to acquire the data for its next burst.

class AudioEngine : StreamCallback {
class AudioEngine : AudioStreamCallback {
public:
DataCallbackResult AudioEngine::onAudioReady(
Stream *oboeStream,
AudioStream *oboeStream,
void *audioData,
int32_t numFrames){
oscillator_->render(static_cast<float *>(audioData), numFrames);
Expand Down Expand Up @@ -322,11 +322,11 @@ 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 : StreamCallback {
class AudioEngine : AudioStreamCallback {
public:

oboe_data_callback_result_t AudioEngine::onAudioReady(
Stream *oboeStream,
AudioStream *oboeStream,
void *audioData,
int32_t numFrames){
Result result =
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(Stream *stream) {
void setRecordingStream(AudioStream *stream) {
recordingStream = stream;
}

private:
Stream *recordingStream;
AudioStream *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 Stream has a *performance mode* which has a large effect on your app's behavior. There are three modes:
Every AudioStream has a *performance mode* which has a large effect on your app's behavior. There are three modes:

* `PerformanceMode::None` is the default mode. It uses a basic stream that balances latency and power savings.
* `PerformanceMode::LowLatency` 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
StreamBuilder builder;
AudioStreamBuilder builder;
builder.setCallback(myCallback);
builder.setPerformanceMode(PerformanceMode::LowLatency);

// Use it to create the stream
Stream *stream;
AudioStream *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 `Stream::getSampleRate()` and `Stream::getChannelCount()`, are thread safe.
Calls that return stream settings, like `AudioStream::getSampleRate()` and `AudioStream::getChannelCount()`, are thread safe.

These calls are also thread safe:

Expand All @@ -409,7 +409,7 @@ These calls are also thread safe:
* `convertSharingModeToText()`
* `convertDataCallbackResultToText()`
* `convertDirectionToText()`
* `Stream::get*()` except for `getTimestamp()`
* `AudioStream::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
16 changes: 8 additions & 8 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 `StreamBuilder`. Create one like this:
Streams are built using an `AudioStreamBuilder`. Create one like this:

oboe::StreamBuilder builder;
oboe::AudioStreamBuilder 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::PerformanceMode::LowLatency);
builder.setSharingMode(oboe::SharingMode::Exclusive);

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

class MyCallback : public oboe::StreamCallback {
class MyCallback : public oboe::AudioStreamCallback {
public:
oboe::Result
onAudioReady(oboe::Stream *audioStream, void *audioData, int32_t numFrames){
onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames){
generateSineWave(static_cast<float *>(audioData), numFrames);
return oboe::DataCallbackResult::Continue;
}
Expand All @@ -76,7 +76,7 @@ Supply this callback class to the builder:

Open the stream:

oboe::Stream *stream;
oboe::AudioStream *stream;
oboe::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`:
Expand All @@ -87,10 +87,10 @@ Check the result to make sure the stream was opened successfully. Oboe has many

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 `StreamCallback::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 `AudioStreamCallback::onAudioReady` callback.

oboe::AudioFormat format = stream->getFormat();
LOGI("Stream format is %s", oboe::convertAudioFormatToText(format));
LOGI("AudioStream format is %s", oboe::convertAudioFormatToText(format));

Now start the stream.

Expand Down
4 changes: 2 additions & 2 deletions build_all_android.sh
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ build_oboe mips
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" " StreamBuilder builder;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " Stream *stream;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " AudioStreamBuilder builder;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " AudioStream *stream;" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " builder.openStream(&stream);" >> ${CDEP_MANIFEST_FILE}
printf "%s\r\n" " }" >> ${CDEP_MANIFEST_FILE}

Expand Down
14 changes: 7 additions & 7 deletions include/oboe/Stream.h → include/oboe/AudioStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
#include <cstdint>
#include <ctime>
#include "oboe/Definitions.h"
#include "oboe/StreamBuilder.h"
#include "oboe/StreamBase.h"
#include "oboe/AudioStreamBuilder.h"
#include "oboe/AudioStreamBase.h"

/** WARNING - UNDER CONSTRUCTION - THIS API WILL CHANGE. */

Expand All @@ -32,13 +32,13 @@ constexpr int64_t kDefaultTimeoutNanos = (2000 * kNanosPerMillisecond);
/**
* Base class for Oboe C++ audio stream.
*/
class Stream : public StreamBase {
class AudioStream : public AudioStreamBase {
public:

Stream() {}
explicit Stream(const StreamBuilder &builder);
AudioStream() {}
explicit AudioStream(const AudioStreamBuilder &builder);

virtual ~Stream() = default;
virtual ~AudioStream() = default;

/**
* Open a stream based on the current settings.
Expand Down Expand Up @@ -144,7 +144,7 @@ class Stream : public StreamBase {

bool isPlaying();

std::shared_ptr<StreamCallback> getCallback() const { return mStreamCallback; }
std::shared_ptr<AudioStreamCallback> getCallback() const { return mStreamCallback; }

int32_t getBytesPerFrame() const { return mChannelCount * getBytesPerSample(); }

Expand Down
16 changes: 8 additions & 8 deletions include/oboe/StreamBase.h → include/oboe/AudioStreamBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#define OBOE_STREAM_BASE_H_

#include <memory>
#include "oboe/StreamCallback.h"
#include "oboe/AudioStreamCallback.h"
#include "oboe/Definitions.h"

namespace oboe {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may or may not want to add an inline version namespace.
http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces
For non template library like Oboe, the advantage of inline version namespace is that symbols of different version will have a different name. Thus preventing a user from linking to the wrong version (aka less user error).
It also allows to have 2 oboe version in the same process.
Though I am not sure we want to support this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention was to have an App statically link to Oboe.
I suppose there could be a problem if an app tried to use with a library that had it's own calls to an old version of Oboe. But that seems unlikely. Most audio libraries just pass PCM in and out and leave the audio I/O to the main app..

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Oboe is static linked, inline version namespace have a lot less attractivity. Do not bother with it.

Expand All @@ -31,17 +31,17 @@ namespace oboe {
* OboeStream will generally return the actual final value, but getFramesPerCallback()
* can be unspecified even for a stream.
*/
class StreamBase {
class AudioStreamBase {
public:

StreamBase() {}
AudioStreamBase() {}

virtual ~StreamBase() = default;
virtual ~AudioStreamBase() = default;

// This class only contains primitives so we can use default constructor and copy methods.
StreamBase(const StreamBase&) = default;
AudioStreamBase(const AudioStreamBase&) = default;

StreamBase& operator=(const StreamBase&) = default;
AudioStreamBase& operator=(const AudioStreamBase&) = default;

/**
* @return number of channels, for example 2 for stereo
Expand Down Expand Up @@ -90,12 +90,12 @@ class StreamBase {

int32_t getDeviceId() const { return mDeviceId; }

std::shared_ptr<StreamCallback> getCallback() const {
std::shared_ptr<AudioStreamCallback> getCallback() const {
return mStreamCallback;
}

protected:
std::shared_ptr<StreamCallback> mStreamCallback;
std::shared_ptr<AudioStreamCallback> mStreamCallback;
int32_t mFramesPerCallback = kUnspecified;
int32_t mChannelCount = kUnspecified;
int32_t mSampleRate = kUnspecified;
Expand Down
Loading