mirror of
https://github.com/love2d/megasource.git
synced 2026-08-18 03:34:25 +02:00
Add Oboe 1.4.3, used only for Android build.
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
[Oboe Docs Home](https://github.com/google/oboe/blob/master/docs/README.md)
|
||||
|
||||
# Oboe Tech Notes
|
||||
|
||||
* [Using Audio Effects with Oboe](effects.md)
|
||||
* [Disconnected Streams](disconnect.md)
|
||||
* [Assert in releaseBuffer()](rlsbuffer.md)
|
||||
@@ -0,0 +1,55 @@
|
||||
[Oboe Docs Home](README.md)
|
||||
|
||||
# Tech Note: Disconnected Streams
|
||||
|
||||
When Oboe is using **OpenSL ES**, and a headset is plugged in or out, then OpenSL ES will automatically switch between devices.
|
||||
This is convenient but can cause problems because the new device may have different burst sizes and different latency.
|
||||
|
||||
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 will then be notified in one of two ways.
|
||||
|
||||
1) If the app is using a callback then the AudioStreamCallback object will be called.
|
||||
It will launch a thread, which will call onErrorBeforeClose().
|
||||
Then it stops and closes the stream.
|
||||
Then onErrorAfterClose() will be called.
|
||||
An app may choose to reopen a stream in the onErrorAfterClose() method.
|
||||
|
||||
2) If an app is using read()/write() calls then they will return an error when a disconnect occurs.
|
||||
The app should then stop() and close() the stream.
|
||||
An app may then choose to reopen a stream.
|
||||
|
||||
## Workaround for not Disconnecting Properly
|
||||
|
||||
On some versions of Android the disconnect message does not reach AAudio and the app will not
|
||||
know that the device has changed. There is a "Test Disconnects" option in
|
||||
[OboeTester](https://github.com/google/oboe/tree/master/apps/OboeTester/docs)
|
||||
that can be used to diagnose this problem.
|
||||
|
||||
As a workaround you can listen for a Java [Intent.ACTION_HEADSET_PLUG](https://developer.android.com/reference/android/content/Intent#ACTION_HEADSET_PLUG),
|
||||
which is fired when a head set is plugged in or out. If your min SDK is LOLLIPOP or later then you can use [AudioManager.ACTION_HEADSET_PLUG](https://developer.android.com/reference/android/media/AudioManager#ACTION_HEADSET_PLUG) instead.
|
||||
|
||||
// Receive a broadcast Intent when a headset is plugged in or unplugged.
|
||||
public class PluginBroadcastReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
// Close the stream if it was not disconnected.
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver mPluginReceiver = new PluginBroadcastReceiver();
|
||||
|
||||
You can register for the Intent when your app resumes and unregister when it pauses.
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
|
||||
this.registerReceiver(mPluginReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.unregisterReceiver(mPluginReceiver);
|
||||
super.onPause();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
[Tech Notes Home](README.md)
|
||||
|
||||
# Using Audio Effects with Oboe
|
||||
|
||||
## Overview
|
||||
|
||||
The Android Audio framework provides some effects processing that can be used by apps.
|
||||
It is available through the Java or Kotlin
|
||||
[AudioEffect API](https://developer.android.com/reference/android/media/audiofx/AudioEffect)
|
||||
|
||||
Another alternative is to do your own effects processing in your own app.
|
||||
|
||||
### Reasons to use the Android AudioEffect in the OS:
|
||||
1. Functions are provided for you so they are easy to use.
|
||||
|
||||
### Reasons to do your own effects Processing:
|
||||
1. They will work on all versions of Android. The AudioEffects can only be used with Oboe on Android 9 (Pie) and above. They are not supported for OpenSL ES.
|
||||
2. You can customize the effects as needed.
|
||||
3. You can get lower latency when you use your own effects. Using Android AudioEffects prevents you from getting a low latency path.
|
||||
|
||||
## Using Android AudioEffects
|
||||
|
||||
Oboe streams on Android 9 (Pie) and above can use the Java/Kotlin.
|
||||
See [AudioEffect API](https://developer.android.com/reference/android/media/audiofx/AudioEffect)
|
||||
|
||||
The basic idea is to use Java or Kotlin to create a Session with Effects.
|
||||
Then associate your Oboe streams with the session by creating them with a SessionID.
|
||||
|
||||
In Java:
|
||||
|
||||
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
int audioSessionId = audioManager.generateAudioSessionId();
|
||||
|
||||
Pass the audioSessionId to your C++ code using JNI. Then use it when opening your Oboe streams:
|
||||
|
||||
builder->setSessionId(sessionId);
|
||||
|
||||
Note that these streams will probably not have low latency. So you may want to do your own effects processing.
|
||||
|
||||
## Using Third Party Affects Processing
|
||||
|
||||
There are many options for finding audio effects.
|
||||
|
||||
- [Music DSP Archive](http://www.musicdsp.org/en/latest/Effects/index.html)
|
||||
- [Synthesis Toolkit in C++ (STK)](https://ccrma.stanford.edu/software/stk/index.html)
|
||||
- [Cookbook for Biquad Filters, EQ, etc.](https://www.w3.org/2011/audio/audio-eq-cookbook.html)
|
||||
- [Faust - language for generating effects, big library](https://faust.grame.fr/index.html)
|
||||
- [DAFX Digital Audio Effects conference proceedings](http://dafx.de/)
|
||||
@@ -0,0 +1,71 @@
|
||||
[Tech Notes Home](README.md)
|
||||
|
||||
# Assert in releaseBuffer()
|
||||
|
||||
There is a bug that can sometimes cause an assert in ClientProxy or AudioTrackShared::releaseBuffer() when headsets are connected or disconnected.
|
||||
The bug was originally reported at: https://github.com/google/oboe/issues/535
|
||||
|
||||
You will see signatures like this in the logcat:
|
||||
|
||||
F AudioTrackShared: releaseBuffer: mUnreleased out of range, !(stepCount:96 <= mUnreleased:0 <= mFrameCount:480), BufferSizeInFrames:480
|
||||
|
||||
## Platforms Affected
|
||||
|
||||
Android version 10 (Q) or earlier.
|
||||
|
||||
Oboe version 1.4.0 or earlier when using OpenSLES with an OUTPUT stream callback.
|
||||
|
||||
OR any version of Oboe if:
|
||||
* Oboe is using using OpenSL ES or a non-MMAP Legacy AAudio stream
|
||||
* AND you call stream->getFramesRead() or stream->getTimestamp(...) from inside
|
||||
an OUTPUT stream callback,
|
||||
|
||||
It does **not** happen when Oboe uses AAudio MMAP because it does not call releaseBuffer().
|
||||
|
||||
## Workarounds
|
||||
|
||||
1. Use Oboe 1.4.1 or later.
|
||||
1. Do not call stream->getFramesRead() or stream->getTimestamp() from inside the callback of an OUTPUT stream. If you absolutely must, then call them at the beginning of your callback to reduce the probability of a crash.
|
||||
|
||||
Here is a [fix in Oboe 1.4.1](https://github.com/google/oboe/pull/863) that removed a call to getPosition().
|
||||
|
||||
## Root Cause
|
||||
|
||||
The sequence of events is:
|
||||
1. AudioFlinger AudioTrack obtains a buffer from the audio device
|
||||
1. user plugs in headphones, which invalidates the audio device
|
||||
1. app is called (callback) to render audio using the buffer
|
||||
1. the app or Oboe calls getFramesRead() or getTimestamp(), which calls down to AudioTrack::getPosition() or AudioTrack::getTimestamp()
|
||||
1. device routing change occurs because the audio device is [invalid](https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libaudioclient/AudioTrack.cpp;l=1239;drc=48e98cf8dbd9fa212a0e129822929dc40e6c3898)
|
||||
1. callback ends by releasing the buffer back to a different device
|
||||
1. AudioTrackShared::releaseBuffer() checks to make sure the device matches the one in ObtainBuffer() and asserts if they do not match.
|
||||
|
||||
Oboe, before V1.4.1, would update the server position in its callback. This called getPosition() in OpenSL ES, which called AudioTrack::getPosition().
|
||||
|
||||
The probability of the assert() is proportional to the time that the CPU spends between obtaining a buffer and calling restoreTrack_l().
|
||||
|
||||
This bug is tracked internally at: b/136268149
|
||||
|
||||
## Reproduce the Bug
|
||||
|
||||
These steps will trigger the bug most of the time:
|
||||
|
||||
1. Install OboeTester 1.5.22 or later, with Oboe < 1.4.1
|
||||
1. Enter in a Terminal window: adb logcat | grep releaseBuffer
|
||||
1. Launch OboeTester
|
||||
1. Click TEST OUTPUT
|
||||
1. Select API: OpenSL ES
|
||||
1. Click OPEN
|
||||
1. Click START, you should hear a tone
|
||||
1. Slide "Workload" fader slowly up until you hear bad glitches.
|
||||
1. Plug in headphones.
|
||||
|
||||
You may see a message like this in the logcat:
|
||||
|
||||
AudioTrackShared: releaseBuffer: mUnreleased out of range, !(stepCount:96 <= mUnreleased:0 <= mFrameCount:480), BufferSizeInFrames:480
|
||||
|
||||
# OEM Information
|
||||
|
||||
These patches are available in Q AOSP:
|
||||
1. [AudioTrack](https://android-review.googlesource.com/c/platform/frameworks/av/+/1251871/)
|
||||
1. [AudioRecord](https://android-review.googlesource.com/c/platform/frameworks/av/+/1251872/)
|
||||
Reference in New Issue
Block a user