aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDon Turner <donturner@google.com>2020-11-20 15:03:11 +0000
committerDon Turner <dturner@users.noreply.github.com>2020-11-24 18:46:38 +0000
commit0a65ae368d8b6a9a749f221448da8a4e90087f53 (patch)
treea76898a67bb2f24c00683ddc6990d8ee75d64fc7
parent429e502a6aa95a2b1415fe8a4de03ad7f53bb0e4 (diff)
downloadoboe-0a65ae368d8b6a9a749f221448da8a4e90087f53.tar.gz
Documentation updates
-rw-r--r--docs/FAQ.md4
-rw-r--r--docs/FullGuide.md40
-rw-r--r--docs/GettingStarted.md18
-rw-r--r--docs/OpenSLESMigration.md12
-rw-r--r--docs/notes/disconnect.md2
5 files changed, 37 insertions, 39 deletions
diff --git a/docs/FAQ.md b/docs/FAQ.md
index a1526467..00d86bb3 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -9,7 +9,7 @@ created with low latency using the AudioTrack.Builder method [`setPerformanceMod
You can dynamically tune the latency of the stream just like in Oboe using [`setBufferSizeInFrames(int)`](https://developer.android.com/reference/android/media/AudioTrack.html#setBufferSizeInFrames(int))
Also you can use blocking writes with the Java AudioTrack and still get a low latency stream.
-Oboe requires a callback to get a low latency stream and that does not work well with Java.
+Oboe requires a data callback to get a low latency stream and that does not work well with Java.
Note that [`AudioTrack.PERFORMANCE_MODE_LOW_LATENCY`](https://developer.android.com/reference/android/media/AudioTrack#PERFORMANCE_MODE_LOW_LATENCY) was added in API 26, For API 24 or 25 use [`AudioAttributes.FLAG_LOW_LATENCY`](https://developer.android.com/reference/kotlin/android/media/AudioAttributes#flag_low_latency). That was deprecated but will still work with later APIs.
@@ -31,7 +31,7 @@ We have had several reports of this happening and are keen to understand the roo
## I requested a stream with `PerformanceMode::LowLatency`, but didn't get it. Why not?
Usually if you call `builder.setPerformanceMode(PerformanceMode::LowLatency)` and don't specify other stream properties you will get a `LowLatency` stream. The most common reasons for not receiving one are:
-- You are opening an output stream and did not specify a **callback**.
+- You are opening an output stream and did not specify a **data callback**.
- You requested a **sample** rate which does not match the audio device's native sample rate. For playback streams, this means the audio data you write into the stream must be resampled before it's sent to the audio device. For recording streams, the audio data must be resampled before you can read it. In both cases the resampling process (performed by the Android audio framework) adds latency and therefore providing a `LowLatency` stream is not possible. To avoid the resampler on API 26 and below you can specify a default value for the sample rate [as detailed here](https://github.com/google/oboe/blob/master/docs/GettingStarted.md#obtaining-optimal-latency). Or you can use the [new resampler](https://google.github.io/oboe/reference/classoboe_1_1_audio_stream_builder.html#af7d24a9ec975d430732151e5ee0d1027) in Oboe, which allows the lower level code to run at the optimal rate and provide lower latency.
- If you request **AudioFormat::Float on an Input** stream before Android 9.0 then you will **not** get a FAST track. You need to either request AudioFormat::Int16 or [enable format conversion by Oboe](https://google.github.io/oboe/reference/classoboe_1_1_audio_stream_builder.html#a7ec5f427cd6fe55cb1ce536ff0cbb4d2).
- The audio **device** does not support `LowLatency` streams, for example Bluetooth.
diff --git a/docs/FullGuide.md b/docs/FullGuide.md
index 1a4a682a..931b67f7 100644
--- a/docs/FullGuide.md
+++ b/docs/FullGuide.md
@@ -111,7 +111,6 @@ The following properties are guaranteed to be set. However, if these properties
are unspecified, a default value will still be set, and should be queried by the
appropriate accessor.
-* callback
* framesPerCallback
* sampleRate
* channelCount
@@ -149,7 +148,7 @@ builder), since it depends on run-time behavior.
The actual size used may not be what was requested.
Oboe or the underlyng API will limit the size between zero and the buffer capacity.
It may also be limited further to reduce glitching on particular devices.
-This features is not supported when using OpenSL ES callbacks.
+This feature is not supported when using a callback with OpenSL ES.
Many of the stream's properties may vary (whether or not you set
them) depending on the capabilities of the audio device and the Android device on
@@ -166,7 +165,8 @@ builder setting:
| AudioStreamBuilder set methods | AudioStream get methods |
| :------------------------ | :----------------- |
-| `setCallback()` | `getCallback()` |
+| `setDataCallback()` | `getDataCallback()` |
+| `setErrorCallback()` | `getErrorCallback()` |
| `setDirection()` | `getDirection()` |
| `setSharingMode()` | `getSharingMode()` |
| `setPerformanceMode()` | `getPerformanceMode()` |
@@ -222,7 +222,7 @@ transition:
Note that you can only request pause or flush on an output stream:
These functions are asynchronous, and the state change doesn't happen
-immediately. When you request a state change, the stream moves toone of the
+immediately. When you request a state change, the stream moves to one of the
corresponding transient states:
* Starting
@@ -276,7 +276,7 @@ while `waitForStateChange()` is running in another thread.
There are two ways to move data in or out of a stream.
1) Read from or write directly to the stream.
-2) Specify a callback object that will get called when the stream is ready.
+2) Specify a data callback object that will get called when the stream is ready.
The callback technique offers the lowest latency performance because the callback code can run in a high priority thread.
Also, attempting to open a low latency output stream without an audio callback (with the intent to use writes)
@@ -329,9 +329,8 @@ 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 calls to `write()` or other functions will return `Result::ErrorDisconnected`. 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 `AudioStreamCallback` and then register your class using `builder.setCallback(yourCallbackClass)`.
+which extends `AudioStreamErrorCallback` and then register your class using `builder.setErrorCallback(yourCallbackClass)`.
If you register a callback, then it will automatically close the stream in a separate thread if the stream is disconnected.
-Note that registering this callback will enable callbacks for both data and errors. So `onAudioReady()` will be called. See the "high priority callback" section below.
Your callback can implement the following methods (called in a separate thread):
@@ -343,7 +342,7 @@ Do not delete the stream or modify its stream state in this callback.
During this callback, stream properties (those requested by the builder) can be queried, as well as frames written and read.
The stream can be deleted at the end of this method (as long as it not referenced in other threads).
Methods that reference the underlying stream should not be called (e.g. `getTimestamp()`, `getXRunCount()`, `read()`, `write()`, etc.).
-Opening a seperate stream is also a valid use of this callback, especially if the error received is `Error::Disconnected`.
+Opening a separate stream is also a valid use of this callback, especially if the error received is `Error::Disconnected`.
However, it is important to note that the new audio device may have vastly different properties than the stream that was disconnected.
@@ -351,7 +350,7 @@ However, it is important to note that the new audio device may have vastly diffe
You can optimize the performance of an audio application by using special high-priority threads.
-### Using a high priority callback
+### Using a high priority data callback
If your app reads or writes audio data from an ordinary thread, it may be preempted or experience timing jitter. This can cause audio glitches.
Using larger buffers might guard against such glitches, but a large buffer also introduces longer audio latency.
@@ -359,10 +358,10 @@ 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
-`AudioStreamCallback`. The stream periodically executes `onAudioReady()` (the
+`AudioStreamDataCallback`. The stream periodically executes `onAudioReady()` (the
callback function) to acquire the data for its next burst.
- class AudioEngine : AudioStreamCallback {
+ class AudioEngine : AudioStreamDataCallback {
public:
DataCallbackResult AudioEngine::onAudioReady(
AudioStream *oboeStream,
@@ -375,7 +374,7 @@ callback function) to acquire the data for its next burst.
bool AudioEngine::start() {
...
// register the callback
- streamBuilder.setCallback(this);
+ streamBuilder.setDataCallback(this);
}
private:
// application data
@@ -383,7 +382,7 @@ callback function) to acquire the data for its next burst.
}
-Note that the callback must be registered on the stream with `setCallback`. Any
+Note that the callback must be registered on the stream with `setDataCallback`. Any
application-specific data (such as `oscillator_` in this case)
can be included within the class itself.
@@ -394,10 +393,10 @@ stream. The input stream is included in the class.
The callback does a non-blocking read from the input stream placing the data into the buffer of the output stream.
- class AudioEngine : AudioStreamCallback {
+ class AudioEngine : AudioStreamDataCallback {
public:
- oboe_data_callback_result_t AudioEngine::onAudioReady(
+ DataCallbackResult AudioEngine::onAudioReady(
AudioStream *oboeStream,
void *audioData,
int32_t numFrames) {
@@ -419,7 +418,7 @@ The callback does a non-blocking read from the input stream placing the data int
bool AudioEngine::start() {
...
- streamBuilder.setCallback(this);
+ streamBuilder.setDataCallback(this);
}
void setRecordingStream(AudioStream *stream) {
@@ -433,7 +432,7 @@ The callback does a non-blocking read from the input stream placing the data int
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.
-#### Callback do's and don'ts
+#### Data Callback - Do's and Don'ts
You should never perform an operation which could block inside `onAudioReady`. Examples of blocking operations include:
- allocate memory using, for example, malloc() or new
@@ -466,7 +465,7 @@ This is useful for apps that are very interactive, such as games or keyboard syn
If saving power is more important than low latency in your application, use `PerformanceMode::PowerSaving`.
This is typical for apps that play back previously generated music, such as streaming audio or MIDI file players.
-In the current version of Oboe, in order to achieve the lowest possible latency you must use the `PerformanceMode::LowLatency` performance mode along with a high-priority callback. Follow this example:
+In the current version of Oboe, in order to achieve the lowest possible latency you must use the `PerformanceMode::LowLatency` performance mode along with a high-priority data callback. Follow this example:
```
// Create a callback object
@@ -474,7 +473,7 @@ MyOboeStreamCallback myCallback;
// Create a stream builder
AudioStreamBuilder builder;
-builder.setCallback(myCallback);
+builder.setDataCallback(myCallback);
builder.setPerformanceMode(PerformanceMode::LowLatency);
// Use it to create the stream
@@ -497,8 +496,7 @@ These calls are also thread safe:
* `convertToText()`
* `AudioStream::get*()` except for `getTimestamp()` and `getState()`
-<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
-from the thread in which it is running.
+<b>Note:</b> When a stream uses an error callback, it's safe to read/write from the callback thread while also closing the stream from the thread in which it is running.
## Code samples
diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md
index 8044f853..2c322140 100644
--- a/docs/GettingStarted.md
+++ b/docs/GettingStarted.md
@@ -149,13 +149,13 @@ The builder's set methods return a pointer to the builder. So they can be easily
oboe::AudioStreamBuilder builder;
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency)
->setSharingMode(oboe::SharingMode::Exclusive)
- ->setCallback(myCallback)
+ ->setDataCallback(myCallback)
->setFormat(oboe::AudioFormat::Float);
```
-Define an `AudioStreamCallback` class to receive callbacks whenever the stream requires new data.
+Define an `AudioStreamDataCallback` class to receive callbacks whenever the stream requires new data.
- class MyCallback : public oboe::AudioStreamCallback {
+ class MyCallback : public oboe::AudioStreamDataCallback {
public:
oboe::DataCallbackResult
onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
@@ -183,7 +183,7 @@ Declare your callback somewhere that it won't get deleted while you are using it
Supply this callback class to the builder:
- builder.setCallback(&myCallback);
+ builder.setDataCallback(&myCallback);
Declare a ManagedStream. Make sure it is declared in an appropriate scope (e.g.the member of a managing class). Avoid declaring it as a global.
```
@@ -203,7 +203,7 @@ Note that this sample code uses the [logging macros from here](https://github.co
## Playing audio
Check the properties of the created stream. If you did not specify a channelCount, sampleRate, or format then you need to
-query the stream to see what you got. The **format** property will dictate the `audioData` type in the `AudioStreamCallback::onAudioReady` callback. If you did specify any of those three properties then you will get what you requested.
+query the stream to see what you got. The **format** property will dictate the `audioData` type in the `AudioStreamDataCallback::onAudioReady` callback. If you did specify any of those three properties then you will get what you requested.
oboe::AudioFormat format = stream->getFormat();
LOGI("AudioStream format is %s", oboe::convertToText(format));
@@ -266,7 +266,7 @@ closes the stream.
#include <oboe/Oboe.h>
#include <math.h>
-class OboeSinePlayer: public oboe::AudioStreamCallback {
+class OboeSinePlayer: public oboe::AudioStreamDataCallback {
public:
@@ -278,7 +278,7 @@ public:
->setChannelCount(kChannelCount)
->setSampleRate(kSampleRate)
->setFormat(oboe::AudioFormat::Float)
- ->setCallback(this)
+ ->setDataCallback(this)
->openManagedStream(outStream);
// Typically, start the stream after querying some stream information, as well as some input from the user
outStream->requestStart();
@@ -314,8 +314,8 @@ private:
```
Note that this implementation computes sine values at run-time for simplicity,
rather than pre-computing them.
-Additionally, best practice is to implement a separate callback class, rather
-than managing the stream and defining its callback in the same class.
+Additionally, best practice is to implement a separate data callback class, rather
+than managing the stream and defining its data callback in the same class.
This class also automatically starts the stream upon construction. Typically,
the stream is queried for information prior to being started (e.g. burst size),
and started upon user input.
diff --git a/docs/OpenSLESMigration.md b/docs/OpenSLESMigration.md
index 3792f96a..ecdf5884 100644
--- a/docs/OpenSLESMigration.md
+++ b/docs/OpenSLESMigration.md
@@ -26,7 +26,7 @@ OpenSL uses an audio engine object, created using `slCreateEngine`, to create ot
OpenSL uses audio player and audio recorder objects to communicate with audio devices. In Oboe an `AudioStream` is used.
-In OpenSL the audio callback mechanism is a user-defined function which is called each time a buffer is enqueued. In Oboe you construct an `AudioStreamCallback` object, and its `onAudioReady` method is called each time audio data is ready to be read or written.
+In OpenSL the audio callback mechanism is a user-defined function which is called each time a buffer is enqueued. In Oboe you construct an `AudioStreamDataCallback` object, and its `onAudioReady` method is called each time audio data is ready to be read or written.
Here's a table which summarizes the object mappings:
@@ -59,7 +59,7 @@ Here's a table which summarizes the object mappings:
<tr>
<td>Callback function
</td>
- <td><code>AudioStreamCallback::onAudioReady</code>
+ <td><code>AudioStreamDataCallback::onAudioReady</code>
</td>
</tr>
</table>
@@ -84,7 +84,7 @@ DataCallbackResult onAudioReady(
```
-You supply your implementation of `onAudioReady` when building the audio stream by constructing an `AudioStreamCallback` object. [Here's an example.](https://github.com/google/oboe/blob/master/docs/GettingStarted.md#creating-an-audio-stream)
+You supply your implementation of `onAudioReady` when building the audio stream by constructing an `AudioStreamDataCallback` object. [Here's an example.](https://github.com/google/oboe/blob/master/docs/GettingStarted.md#creating-an-audio-stream)
### Buffer sizes
@@ -124,7 +124,7 @@ However, you may want to specify some properties. These are set using the `Audio
OpenSL has no mechanism, other than stopping callbacks, to indicate that an audio device has been disconnected - for example, when headphones are unplugged.
-In Oboe, you can be notified of stream disconnection by overriding one of the `onError` methods in `AudioStreamCallback`. This allows you to clean up any resources associated with the audio stream and create a new stream with optimal properties for the current audio device ([more info](https://github.com/google/oboe/blob/master/docs/FullGuide.md#disconnected-audio-stream)).
+In Oboe, you can be notified of stream disconnection by overriding one of the `onError` methods in `AudioStreamErrorCallback`. This allows you to clean up any resources associated with the audio stream and create a new stream with optimal properties for the current audio device ([more info](https://github.com/google/oboe/blob/master/docs/FullGuide.md#disconnected-audio-stream)).
# Unsupported features
@@ -162,8 +162,8 @@ Oboe does **not** support the following features:
* Replace your audio player or recorder with an `AudioStream` created using an `AudioStreamBuilder`.
* Use your value for `numBuffers` to set the audio stream's buffer size as a multiple of the burst size. For example: `audioStream.setBufferSizeInFrames(audioStream.getFramesPerBurst * numBuffers)`.
-* Create an `AudioStreamCallback` object and move your OpenSL callback code inside the `onAudioReady` method.
-* Handle stream disconnect events by overriding one of the `AudioStreamCallback::onError` methods.
+* Create an `AudioStreamDataCallback` object and move your OpenSL callback code inside the `onAudioReady` method.
+* Handle stream disconnect events by creating an `AudioStreamErrorCallback` object and overriding one of its `onError` methods.
* Pass sensible default sample rate and buffer size values to Oboe from `AudioManager` [using this method](https://github.com/google/oboe/blob/master/docs/GettingStarted.md#obtaining-optimal-latency) so that your app is still performant on older devices.
For more information please read the [Full Guide to Oboe](https://github.com/google/oboe/blob/master/docs/FullGuide.md).
diff --git a/docs/notes/disconnect.md b/docs/notes/disconnect.md
index 5b5abf2b..08ee633b 100644
--- a/docs/notes/disconnect.md
+++ b/docs/notes/disconnect.md
@@ -9,7 +9,7 @@ When Oboe is using **AAudio**, and a headset is plugged in or out, then
the stream is no longer available and becomes "disconnected".
The app should then be notified in one of two ways.
-1) If the app is using a callback then the AudioStreamCallback object will be called.
+1) If the app is using an error callback then the AudioStreamErrorCallback methods will be called.
It will launch a thread, which will call onErrorBeforeClose().
Then it stops and closes the stream.
Then onErrorAfterClose() will be called.