From fe322590cce08bba784c6fdca99051c2e104ba54 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 22 Jul 2022 00:23:11 -0500 Subject: [PATCH] Add an option to allow equalizer effects --- app/src/main/java/com/limelight/Game.java | 4 +- .../limelight/binding/PlatformBinding.java | 10 ----- .../binding/audio/AndroidAudioRenderer.java | 38 ++++++++++++++++++- .../preferences/PreferenceConfiguration.java | 4 ++ app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/preferences.xml | 5 +++ 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index baf0bc20..f8b05642 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -2,6 +2,7 @@ package com.limelight; import com.limelight.binding.PlatformBinding; +import com.limelight.binding.audio.AndroidAudioRenderer; import com.limelight.binding.input.ControllerHandler; import com.limelight.binding.input.KeyboardTranslator; import com.limelight.binding.input.capture.InputCaptureManager; @@ -1920,7 +1921,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, UiHelper.notifyStreamConnecting(Game.this); decoderRenderer.setRenderTarget(holder); - conn.start(PlatformBinding.getAudioRenderer(), decoderRenderer, Game.this); + conn.start(new AndroidAudioRenderer(Game.this, prefConfig.enableAudioFx), + decoderRenderer, Game.this); } } diff --git a/app/src/main/java/com/limelight/binding/PlatformBinding.java b/app/src/main/java/com/limelight/binding/PlatformBinding.java index b37c7645..73bb2a30 100644 --- a/app/src/main/java/com/limelight/binding/PlatformBinding.java +++ b/app/src/main/java/com/limelight/binding/PlatformBinding.java @@ -8,16 +8,6 @@ import com.limelight.nvstream.av.audio.AudioRenderer; import com.limelight.nvstream.http.LimelightCryptoProvider; public class PlatformBinding { - public static String getDeviceName() { - String deviceName = android.os.Build.MODEL; - deviceName = deviceName.replace(" ", ""); - return deviceName; - } - - public static AudioRenderer getAudioRenderer() { - return new AndroidAudioRenderer(); - } - public static LimelightCryptoProvider getCryptoProvider(Context c) { return new AndroidCryptoProvider(c); } diff --git a/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java b/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java index bbecec63..7c7776bc 100644 --- a/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java +++ b/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java @@ -1,9 +1,12 @@ package com.limelight.binding.audio; +import android.content.Context; +import android.content.Intent; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; +import android.media.audiofx.AudioEffect; import android.os.Build; import com.limelight.LimeLog; @@ -12,8 +15,16 @@ import com.limelight.nvstream.jni.MoonBridge; public class AndroidAudioRenderer implements AudioRenderer { + private final Context context; + private final boolean enableAudioFx; + private AudioTrack track; + public AndroidAudioRenderer(Context context, boolean enableAudioFx) { + this.context = context; + this.enableAudioFx = enableAudioFx; + } + private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return new AudioTrack(AudioManager.STREAM_MUSIC, @@ -161,6 +172,12 @@ public class AndroidAudioRenderer implements AudioRenderer { continue; } + // Skip low latency options when using audio effects, since low latency mode + // precludes the use of the audio effect pipeline (as of Android 13). + if (enableAudioFx && lowLatency) { + continue; + } + try { track = createAudioTrack(channelConfig, sampleRate, bufferSize, lowLatency); track.play(); @@ -203,10 +220,27 @@ public class AndroidAudioRenderer implements AudioRenderer { } @Override - public void start() {} + public void start() { + if (enableAudioFx) { + // Open an audio effect control session to allow equalizers to apply audio effects + Intent i = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); + i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, track.getAudioSessionId()); + i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName()); + i.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_GAME); + context.sendBroadcast(i); + } + } @Override - public void stop() {} + public void stop() { + if (enableAudioFx) { + // Close our audio effect control session when we're stopping + Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION); + i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, track.getAudioSessionId()); + i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName()); + context.sendBroadcast(i); + } + } @Override public void cleanup() { diff --git a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java index 8720ec00..f19592e0 100644 --- a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java +++ b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java @@ -45,6 +45,7 @@ public class PreferenceConfiguration { private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast"; private static final String FRAME_PACING_PREF_STRING = "frame_pacing"; private static final String ABSOLUTE_MOUSE_MODE_PREF_STRING = "checkbox_absolute_mouse_mode"; + private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx"; static final String DEFAULT_RESOLUTION = "1280x720"; static final String DEFAULT_FPS = "60"; @@ -75,6 +76,7 @@ public class PreferenceConfiguration { private static final boolean DEFAULT_LATENCY_TOAST = false; private static final String DEFAULT_FRAME_PACING = "latency"; private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false; + private static final boolean DEFAULT_ENABLE_AUDIO_FX = false; public static final int FORCE_H265_ON = -1; public static final int AUTOSELECT_H265 = 0; @@ -117,6 +119,7 @@ public class PreferenceConfiguration { public MoonBridge.AudioConfiguration audioConfiguration; public int framePacing; public boolean absoluteMouseMode; + public boolean enableAudioFx; public static boolean isNativeResolution(int width, int height) { // It's not a native resolution if it matches an existing resolution option @@ -471,6 +474,7 @@ public class PreferenceConfiguration { config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD); config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST); config.absoluteMouseMode = prefs.getBoolean(ABSOLUTE_MOUSE_MODE_PREF_STRING, DEFAULT_ABSOLUTE_MOUSE_MODE); + config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX); return config; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4b672c16..1fb47e5b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -156,6 +156,8 @@ Audio Settings Surround sound configuration Enable 5.1 or 7.1 surround sound for home-theater systems + Enable system equalizer support + Allows audio effects to function while streaming, but may increase audio latency Input Settings Use the touchscreen as a trackpad diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 9a3627c2..1add66f0 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -49,6 +49,11 @@ android:entries="@array/audio_config_names" android:entryValues="@array/audio_config_values" android:defaultValue="2" /> +