You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/FAQ.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ created with low latency using the AudioTrack.Builder method [`setPerformanceMod
9
9
10
10
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))
11
11
Also you can use blocking writes with the Java AudioTrack and still get a low latency stream.
12
-
Oboe requires a callback to get a low latency stream and that does not work well with Java.
12
+
Oboe requires a data callback to get a low latency stream and that does not work well with Java.
13
13
14
14
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.
15
15
@@ -31,7 +31,7 @@ We have had several reports of this happening and are keen to understand the roo
31
31
## I requested a stream with `PerformanceMode::LowLatency`, but didn't get it. Why not?
32
32
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:
33
33
34
-
- You are opening an output stream and did not specify a **callback**.
34
+
- You are opening an output stream and did not specify a **data callback**.
35
35
- 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.
36
36
- 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).
37
37
- The audio **device** does not support `LowLatency` streams, for example Bluetooth.
Note that you can only request pause or flush on an output stream:
223
223
224
224
These functions are asynchronous, and the state change doesn't happen
225
-
immediately. When you request a state change, the stream moves toone of the
225
+
immediately. When you request a state change, the stream moves to one of the
226
226
corresponding transient states:
227
227
228
228
* Starting
@@ -276,7 +276,7 @@ while `waitForStateChange()` is running in another thread.
276
276
277
277
There are two ways to move data in or out of a stream.
278
278
1) Read from or write directly to the stream.
279
-
2) Specify a callback object that will get called when the stream is ready.
279
+
2) Specify a data callback object that will get called when the stream is ready.
280
280
281
281
The callback technique offers the lowest latency performance because the callback code can run in a high priority thread.
282
282
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
329
329
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.
330
330
331
331
If you need to be informed when an audio device is disconnected, write a class
332
-
which extends `AudioStreamCallback` and then register your class using `builder.setCallback(yourCallbackClass)`.
332
+
which extends `AudioStreamErrorCallback` and then register your class using `builder.setErrorCallback(yourCallbackClass)`.
333
333
If you register a callback, then it will automatically close the stream in a separate thread if the stream is disconnected.
334
-
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.
335
334
336
335
Your callback can implement the following methods (called in a separate thread):
337
336
@@ -343,26 +342,26 @@ Do not delete the stream or modify its stream state in this callback.
343
342
During this callback, stream properties (those requested by the builder) can be queried, as well as frames written and read.
344
343
The stream can be deleted at the end of this method (as long as it not referenced in other threads).
345
344
Methods that reference the underlying stream should not be called (e.g. `getTimestamp()`, `getXRunCount()`, `read()`, `write()`, etc.).
346
-
Opening a seperate stream is also a valid use of this callback, especially if the error received is `Error::Disconnected`.
345
+
Opening a separate stream is also a valid use of this callback, especially if the error received is `Error::Disconnected`.
347
346
However, it is important to note that the new audio device may have vastly different properties than the stream that was disconnected.
348
347
349
348
350
349
## Optimizing performance
351
350
352
351
You can optimize the performance of an audio application by using special high-priority threads.
353
352
354
-
### Using a high priority callback
353
+
### Using a high priority data callback
355
354
356
355
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.
357
356
Using larger buffers might guard against such glitches, but a large buffer also introduces longer audio latency.
358
357
For applications that require low latency, an audio stream can use an asynchronous callback function to transfer data to and from your app.
359
358
The callback runs in a high-priority thread that has better performance.
360
359
361
360
Your code can access the callback mechanism by implementing the virtual class
362
-
`AudioStreamCallback`. The stream periodically executes `onAudioReady()` (the
361
+
`AudioStreamDataCallback`. The stream periodically executes `onAudioReady()` (the
363
362
callback function) to acquire the data for its next burst.
364
363
365
-
class AudioEngine : AudioStreamCallback {
364
+
class AudioEngine : AudioStreamDataCallback {
366
365
public:
367
366
DataCallbackResult AudioEngine::onAudioReady(
368
367
AudioStream *oboeStream,
@@ -375,15 +374,15 @@ callback function) to acquire the data for its next burst.
375
374
bool AudioEngine::start() {
376
375
...
377
376
// register the callback
378
-
streamBuilder.setCallback(this);
377
+
streamBuilder.setDataCallback(this);
379
378
}
380
379
private:
381
380
// application data
382
381
Oscillator* oscillator_;
383
382
}
384
383
385
384
386
-
Note that the callback must be registered on the stream with `setCallback`. Any
385
+
Note that the callback must be registered on the stream with `setDataCallback`. Any
387
386
application-specific data (such as `oscillator_` in this case)
388
387
can be included within the class itself.
389
388
@@ -394,10 +393,10 @@ stream. The input stream is included in the class.
394
393
395
394
The callback does a non-blocking read from the input stream placing the data into the buffer of the output stream.
@@ -419,7 +418,7 @@ The callback does a non-blocking read from the input stream placing the data int
419
418
420
419
bool AudioEngine::start() {
421
420
...
422
-
streamBuilder.setCallback(this);
421
+
streamBuilder.setDataCallback(this);
423
422
}
424
423
425
424
void setRecordingStream(AudioStream *stream) {
@@ -433,7 +432,7 @@ The callback does a non-blocking read from the input stream placing the data int
433
432
434
433
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.
435
434
436
-
#### Callback do's and don'ts
435
+
#### Data Callback - Do's and Don'ts
437
436
You should never perform an operation which could block inside `onAudioReady`. Examples of blocking operations include:
438
437
439
438
- allocate memory using, for example, malloc() or new
@@ -466,15 +465,15 @@ This is useful for apps that are very interactive, such as games or keyboard syn
466
465
If saving power is more important than low latency in your application, use `PerformanceMode::PowerSaving`.
467
466
This is typical for apps that play back previously generated music, such as streaming audio or MIDI file players.
468
467
469
-
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:
468
+
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:
@@ -497,8 +496,7 @@ These calls are also thread safe:
497
496
*`convertToText()`
498
497
*`AudioStream::get*()` except for `getTimestamp()` and `getState()`
499
498
500
-
<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
501
-
from the thread in which it is running.
499
+
<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.
@@ -183,7 +183,7 @@ Declare your callback somewhere that it won't get deleted while you are using it
183
183
184
184
Supply this callback class to the builder:
185
185
186
-
builder.setCallback(&myCallback);
186
+
builder.setDataCallback(&myCallback);
187
187
188
188
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.
189
189
```
@@ -203,7 +203,7 @@ Note that this sample code uses the [logging macros from here](https://github.co
203
203
204
204
## Playing audio
205
205
Check the properties of the created stream. If you did not specify a channelCount, sampleRate, or format then you need to
206
-
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.
206
+
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.
207
207
208
208
oboe::AudioFormat format = stream->getFormat();
209
209
LOGI("AudioStream format is %s", oboe::convertToText(format));
@@ -266,7 +266,7 @@ closes the stream.
266
266
#include <oboe/Oboe.h>
267
267
#include <math.h>
268
268
269
-
class OboeSinePlayer: public oboe::AudioStreamCallback {
269
+
class OboeSinePlayer: public oboe::AudioStreamDataCallback {
270
270
public:
271
271
272
272
@@ -278,7 +278,7 @@ public:
278
278
->setChannelCount(kChannelCount)
279
279
->setSampleRate(kSampleRate)
280
280
->setFormat(oboe::AudioFormat::Float)
281
-
->setCallback(this)
281
+
->setDataCallback(this)
282
282
->openManagedStream(outStream);
283
283
// Typically, start the stream after querying some stream information, as well as some input from the user
284
284
outStream->requestStart();
@@ -314,8 +314,8 @@ private:
314
314
```
315
315
Note that this implementation computes sine values at run-time for simplicity,
316
316
rather than pre-computing them.
317
-
Additionally, best practice is to implement a separate callback class, rather
318
-
than managing the stream and defining its callback in the same class.
317
+
Additionally, best practice is to implement a separate data callback class, rather
318
+
than managing the stream and defining its data callback in the same class.
319
319
This class also automatically starts the stream upon construction. Typically,
320
320
the stream is queried for information prior to being started (e.g. burst size),
Copy file name to clipboardExpand all lines: docs/OpenSLESMigration.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -26,7 +26,7 @@ OpenSL uses an audio engine object, created using `slCreateEngine`, to create ot
26
26
27
27
OpenSL uses audio player and audio recorder objects to communicate with audio devices. In Oboe an `AudioStream` is used.
28
28
29
-
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.
29
+
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.
30
30
31
31
Here's a table which summarizes the object mappings:
32
32
@@ -59,7 +59,7 @@ Here's a table which summarizes the object mappings:
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)
87
+
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)
88
88
89
89
90
90
### Buffer sizes
@@ -124,7 +124,7 @@ However, you may want to specify some properties. These are set using the `Audio
124
124
125
125
OpenSL has no mechanism, other than stopping callbacks, to indicate that an audio device has been disconnected - for example, when headphones are unplugged.
126
126
127
-
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)).
127
+
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)).
128
128
129
129
130
130
# Unsupported features
@@ -162,8 +162,8 @@ Oboe does **not** support the following features:
162
162
163
163
* Replace your audio player or recorder with an `AudioStream` created using an `AudioStreamBuilder`.
164
164
* 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)`.
165
-
* Create an `AudioStreamCallback` object and move your OpenSL callback code inside the `onAudioReady` method.
166
-
* Handle stream disconnect events by overriding one of the `AudioStreamCallback::onError` methods.
165
+
* Create an `AudioStreamDataCallback` object and move your OpenSL callback code inside the `onAudioReady` method.
166
+
* Handle stream disconnect events by creating an `AudioStreamErrorCallback` object and overriding one of its `onError` methods.
167
167
* 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.
168
168
169
169
For more information please read the [Full Guide to Oboe](https://github.com/google/oboe/blob/master/docs/FullGuide.md).
0 commit comments