android: expose sound latency setting. default to auto

Issue #182
remove video Clipping option
remove audio LimitFPS option
This commit is contained in:
Flyinghead 2021-03-16 10:15:23 +01:00
parent bceed97817
commit 58c936fa6c
5 changed files with 45 additions and 30 deletions

View File

@ -40,7 +40,6 @@ Option<bool> AutoSavestate("Dreamcast.AutoSavestate");
// Sound // Sound
Option<bool> LimitFPS("aica.LimitFPS", true);
Option<bool> DSPEnabled("aica.DSPEnabled", false); Option<bool> DSPEnabled("aica.DSPEnabled", false);
Option<bool> DisableSound("aica.NoSound"); Option<bool> DisableSound("aica.NoSound");
#if HOST_CPU == CPU_ARM #if HOST_CPU == CPU_ARM
@ -48,6 +47,13 @@ Option<int> AudioBufferSize("aica.BufferSize", 5644); // 128 ms
#else #else
Option<int> AudioBufferSize("aica.BufferSize", 2822); // 64 ms Option<int> AudioBufferSize("aica.BufferSize", 2822); // 64 ms
#endif #endif
Option<bool> AutoLatency("aica.AutoLatency",
#ifdef __ANDROID__
true
#else
false
#endif
);
OptionString AudioBackend("backend", "auto", "audio"); OptionString AudioBackend("backend", "auto", "audio");
@ -61,7 +67,6 @@ Option<bool> RenderToTextureBuffer("rend.RenderToTextureBuffer");
Option<int> RenderToTextureUpscale("rend.RenderToTextureUpscale", 1); Option<int> RenderToTextureUpscale("rend.RenderToTextureUpscale", 1);
Option<bool> TranslucentPolygonDepthMask("rend.TranslucentPolygonDepthMask"); Option<bool> TranslucentPolygonDepthMask("rend.TranslucentPolygonDepthMask");
Option<bool> ModifierVolumes("rend.ModifierVolumes", true); Option<bool> ModifierVolumes("rend.ModifierVolumes", true);
Option<bool> Clipping("rend.Clipping", true);
Option<int> TextureUpscale("rend.TextureUpscale", 1); Option<int> TextureUpscale("rend.TextureUpscale", 1);
Option<int> MaxFilteredTextureSize("rend.MaxFilteredTextureSize", 256); Option<int> MaxFilteredTextureSize("rend.MaxFilteredTextureSize", 256);
Option<float> ExtraDepthScale("rend.ExtraDepthScale", 1.f); Option<float> ExtraDepthScale("rend.ExtraDepthScale", 1.f);

View File

@ -277,6 +277,12 @@ protected:
using OptionString = Option<std::string>; using OptionString = Option<std::string>;
template<typename T, T value = T()>
class ConstOption {
public:
operator T() const { return value; }
};
// Dynarec // Dynarec
extern Option<bool> DynarecEnabled; extern Option<bool> DynarecEnabled;
@ -297,10 +303,11 @@ extern Option<bool> AutoSavestate;
// Sound // Sound
extern Option<bool> LimitFPS; constexpr ConstOption<bool, true> LimitFPS;
extern Option<bool> DSPEnabled; extern Option<bool> DSPEnabled;
extern Option<bool> DisableSound; extern Option<bool> DisableSound;
extern Option<int> AudioBufferSize; //In samples ,*4 for bytes (1024) extern Option<int> AudioBufferSize; //In samples ,*4 for bytes
extern Option<bool> AutoLatency;
extern OptionString AudioBackend; extern OptionString AudioBackend;
@ -352,7 +359,7 @@ extern Option<bool> RenderToTextureBuffer;
extern Option<int> RenderToTextureUpscale; extern Option<int> RenderToTextureUpscale;
extern Option<bool> TranslucentPolygonDepthMask; extern Option<bool> TranslucentPolygonDepthMask;
extern Option<bool> ModifierVolumes; extern Option<bool> ModifierVolumes;
extern Option<bool> Clipping; constexpr ConstOption<bool, true> Clipping;
extern Option<int> TextureUpscale; extern Option<int> TextureUpscale;
extern Option<int> MaxFilteredTextureSize; extern Option<int> MaxFilteredTextureSize;
extern Option<float> ExtraDepthScale; extern Option<float> ExtraDepthScale;

View File

@ -1,20 +1,20 @@
/* /*
Copyright 2019 flyinghead Copyright 2019 flyinghead
This file is part of reicast. This file is part of Flycast.
reicast is free software: you can redistribute it and/or modify Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
reicast is distributed in the hope that it will be useful, Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with reicast. If not, see <https://www.gnu.org/licenses/>. along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <mutex> #include <mutex>
@ -1007,7 +1007,7 @@ static void gui_display_settings()
ImGui::ListBoxFooter(); ImGui::ListBoxFooter();
} }
ImGui::SameLine(); ImGui::SameLine();
ShowHelpMarker("The directory where reicast saves configuration files and VMUs. BIOS files should be in a subfolder named \"data\""); ShowHelpMarker("The directory where Flycast saves configuration files and VMUs. BIOS files should be in a subfolder named \"data\"");
if (OptionCheckbox("Hide Legacy Naomi Roms", config::HideLegacyNaomiRoms, if (OptionCheckbox("Hide Legacy Naomi Roms", config::HideLegacyNaomiRoms,
"Hide .bin, .dat and .lst files from the content browser")) "Hide .bin, .dat and .lst files from the content browser"))
scanner.refresh(); scanner.refresh();
@ -1245,8 +1245,6 @@ static void gui_display_settings()
OptionRadioButton("Maximum", config::AutoSkipFrame, 2, "Skip a frame when the GPU is running slow"); OptionRadioButton("Maximum", config::AutoSkipFrame, 2, "Skip a frame when the GPU is running slow");
ImGui::Columns(1, nullptr, false); ImGui::Columns(1, nullptr, false);
OptionCheckbox("Clipping", config::Clipping,
"Enable clipping. May produce graphical errors when disabled");
OptionCheckbox("Shadows", config::ModifierVolumes, OptionCheckbox("Shadows", config::ModifierVolumes,
"Enable modifier volumes, usually used for shadows"); "Enable modifier volumes, usually used for shadows");
OptionCheckbox("Fog", config::Fog, "Enable fog effects"); OptionCheckbox("Fog", config::Fog, "Enable fog effects");
@ -1342,14 +1340,19 @@ static void gui_display_settings()
OptionCheckbox("Disable Sound", config::DisableSound, "Disable the emulator sound output"); OptionCheckbox("Disable Sound", config::DisableSound, "Disable the emulator sound output");
OptionCheckbox("Enable DSP", config::DSPEnabled, OptionCheckbox("Enable DSP", config::DSPEnabled,
"Enable the Dreamcast Digital Sound Processor. Only recommended on fast platforms"); "Enable the Dreamcast Digital Sound Processor. Only recommended on fast platforms");
OptionCheckbox("Limit Emulator Speed", config::LimitFPS, #if !defined(_WIN32)
"Whether to limit the emulator speed using the audio output. Recommended"); #ifdef __ANDROID__
#if !defined(__ANDROID__) && !defined(_WIN32) OptionCheckbox("Automatic Latency", config::AutoLatency,
int latency = (int)roundf(config::AudioBufferSize * 1000.f / 44100.f); "Automatically set audio latency. Recommended");
ImGui::SliderInt("Latency", &latency, 12, 512, "%d ms"); #endif
config::AudioBufferSize = (int)roundf(latency * 44100.f / 1000.f); if (!config::AutoLatency)
ImGui::SameLine(); {
ShowHelpMarker("Sets the maximum audio latency. Not supported by all audio drivers."); int latency = (int)roundf(config::AudioBufferSize * 1000.f / 44100.f);
ImGui::SliderInt("Latency", &latency, 12, 512, "%d ms");
config::AudioBufferSize = (int)roundf(latency * 44100.f / 1000.f);
ImGui::SameLine();
ShowHelpMarker("Sets the maximum audio latency. Not supported by all audio drivers.");
}
#endif #endif
audiobackend_t* backend = nullptr; audiobackend_t* backend = nullptr;
@ -1711,7 +1714,7 @@ static void gui_display_content()
} }
else else
{ {
std::string gamePath(game.path); std::string gamePath(game.path);
scanner.get_mutex().unlock(); scanner.get_mutex().unlock();
gui_state = GuiState::Closed; gui_state = GuiState::Closed;
gui_start_game(gamePath); gui_start_game(gamePath);

View File

@ -24,12 +24,12 @@ public final class AudioBackend {
} }
// Called by native code // Called by native code
private void init() private void init(int bufferSize)
{ {
int bufferSize = 2048; if (bufferSize == 0)
int min = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); bufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize < min) else
bufferSize = min; bufferSize *= 4;
audioTrack = new AudioTrack( audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC, AudioManager.STREAM_MUSIC,
@ -48,7 +48,7 @@ public final class AudioBackend {
size = bufferSize / 4; size = bufferSize / 4;
writePosition = 0; writePosition = 0;
Log.i("audcfg", "Audio streaming: buffer size " + size + " samples / " + size / 44100.0 + " ms"); Log.i("audcfg", "Audio streaming: buffer size " + size + " samples / " + size * 1000.0 / 44100.0 + " ms");
audioTrack.play(); audioTrack.play();
} }

View File

@ -469,14 +469,14 @@ JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsContentBrows
static u32 androidaudio_push(const void* frame, u32 amt, bool wait) static u32 androidaudio_push(const void* frame, u32 amt, bool wait)
{ {
verify(amt==SAMPLE_COUNT); verify(amt==SAMPLE_COUNT);
//yeah, do some audio piping magic here !
jvm_attacher.getEnv()->SetShortArrayRegion(jsamples, 0, amt * 2, (jshort *)frame); jvm_attacher.getEnv()->SetShortArrayRegion(jsamples, 0, amt * 2, (jshort *)frame);
return jvm_attacher.getEnv()->CallIntMethod(g_audioBackend, writeBufferMid, jsamples, wait); return jvm_attacher.getEnv()->CallIntMethod(g_audioBackend, writeBufferMid, jsamples, wait);
} }
static void androidaudio_init() static void androidaudio_init()
{ {
jvm_attacher.getEnv()->CallVoidMethod(g_audioBackend, audioInitMid); jint bufferSize = config::AutoLatency ? 0 : config::AudioBufferSize;
jvm_attacher.getEnv()->CallVoidMethod(g_audioBackend, audioInitMid, bufferSize);
} }
static void androidaudio_term() static void androidaudio_term()
@ -539,7 +539,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_AudioBackend_setInstance(JN
else { else {
g_audioBackend = env->NewGlobalRef(instance); g_audioBackend = env->NewGlobalRef(instance);
writeBufferMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "writeBuffer", "([SZ)I"); writeBufferMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "writeBuffer", "([SZ)I");
audioInitMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "init", "()V"); audioInitMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "init", "(I)V");
audioTermMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "term", "()V"); audioTermMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "term", "()V");
if (jsamples == NULL) { if (jsamples == NULL) {
jsamples = env->NewShortArray(SAMPLE_COUNT * 2); jsamples = env->NewShortArray(SAMPLE_COUNT * 2);