From bf150ecddb4fdde988252a3ad23341d2b1226def Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 25 Nov 2012 19:21:26 +0200 Subject: [PATCH] Compatibility hack for apps that ignore audio buffer size that SDL gives them --- changeAppSettings.sh | 19 ++++++- .../openarena/AndroidAppSettings.cfg | 1 + .../src/audio/android/SDL_androidaudio.c | 53 ++++++++++++++++--- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/changeAppSettings.sh b/changeAppSettings.sh index 8f22ee92b..4d18832bd 100755 --- a/changeAppSettings.sh +++ b/changeAppSettings.sh @@ -285,6 +285,16 @@ if [ -n "$var" ] ; then fi fi +if [ -z "$CompatibilityHacksAppIgnoresAudioBufferSize" -o -z "$AUTO" ]; then +echo +echo -n "Hack for broken apps: application ignores audio buffer size returned by SDL (y)/(n) ($CompatibilityHacksAppIgnoresAudioBufferSize): " +read var +if [ -n "$var" ] ; then + CompatibilityHacksAppIgnoresAudioBufferSize="$var" + CHANGED=1 +fi +fi + if [ -z "$AppUsesJoystick" -o -z "$AUTO" ]; then echo echo "Application uses joystick (y) or (n), the on-screen DPAD will be used" @@ -651,6 +661,7 @@ echo CompatibilityHacks=$CompatibilityHacks >> AndroidAppSettings.cfg echo CompatibilityHacksStaticInit=$CompatibilityHacksStaticInit >> AndroidAppSettings.cfg echo CompatibilityHacksTextInputEmulatesHwKeyboard=$CompatibilityHacksTextInputEmulatesHwKeyboard >> AndroidAppSettings.cfg echo CompatibilityHacksPreventAudioChopping=$CompatibilityHacksPreventAudioChopping >> AndroidAppSettings.cfg +echo CompatibilityHacksAppIgnoresAudioBufferSize=$CompatibilityHacksAppIgnoresAudioBufferSize >> AndroidAppSettings.cfg echo AppUsesMouse=$AppUsesMouse >> AndroidAppSettings.cfg echo AppNeedsTwoButtonMouse=$AppNeedsTwoButtonMouse >> AndroidAppSettings.cfg echo ShowMouseCursor=$ShowMouseCursor >> AndroidAppSettings.cfg @@ -772,6 +783,12 @@ else CompatibilityHacksPreventAudioChopping= fi +if [ "$CompatibilityHacksAppIgnoresAudioBufferSize" = "y" ] ; then + CompatibilityHacksAppIgnoresAudioBufferSize=-DSDL_AUDIO_APP_IGNORES_RETURNED_BUFFER_SIZE=1 +else + CompatibilityHacksAppIgnoresAudioBufferSize= +fi + if [ "$AppUsesMouse" = "y" ] ; then AppUsesMouse=true else @@ -983,7 +1000,7 @@ cat project/jni/SettingsTemplate.mk | \ sed "s^COMPILED_LIBRARIES := .*^COMPILED_LIBRARIES := $CompiledLibraries^" | \ sed "s^APPLICATION_ADDITIONAL_CFLAGS :=.*^APPLICATION_ADDITIONAL_CFLAGS := $AppCflags^" | \ sed "s^APPLICATION_ADDITIONAL_LDFLAGS :=.*^APPLICATION_ADDITIONAL_LDFLAGS := $AppLdflags^" | \ - sed "s^SDL_ADDITIONAL_CFLAGS :=.*^SDL_ADDITIONAL_CFLAGS := $RedefinedKeycodes $RedefinedKeycodesScreenKb $CompatibilityHacksPreventAudioChopping^" | \ + sed "s^SDL_ADDITIONAL_CFLAGS :=.*^SDL_ADDITIONAL_CFLAGS := $RedefinedKeycodes $RedefinedKeycodesScreenKb $CompatibilityHacksPreventAudioChopping $CompatibilityHacksAppIgnoresAudioBufferSize^" | \ sed "s^APPLICATION_SUBDIRS_BUILD :=.*^APPLICATION_SUBDIRS_BUILD := $AppSubdirsBuild^" | \ sed "s^APPLICATION_CUSTOM_BUILD_SCRIPT :=.*^APPLICATION_CUSTOM_BUILD_SCRIPT := $CustomBuildScript^" | \ sed "s^SDL_VERSION :=.*^SDL_VERSION := $LibSdlVersion^" >> \ diff --git a/project/jni/application/openarena/AndroidAppSettings.cfg b/project/jni/application/openarena/AndroidAppSettings.cfg index 033b74560..7f8fb5330 100644 --- a/project/jni/application/openarena/AndroidAppSettings.cfg +++ b/project/jni/application/openarena/AndroidAppSettings.cfg @@ -17,6 +17,7 @@ CompatibilityHacks=n CompatibilityHacksStaticInit=n CompatibilityHacksTextInputEmulatesHwKeyboard=n CompatibilityHacksPreventAudioChopping=n +CompatibilityHacksAppIgnoresAudioBufferSize=n AppUsesMouse=n AppNeedsTwoButtonMouse=n ShowMouseCursor=n diff --git a/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c b/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c index b3cd08c9d..e63e98cfd 100644 --- a/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c +++ b/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c @@ -38,6 +38,8 @@ #include // for memset() #include +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + #define _THIS SDL_AudioDevice *this /* Audio driver functions */ @@ -131,6 +133,9 @@ AudioBootStrap ANDROIDAUD_bootstrap = { static unsigned char * audioBuffer = NULL; static size_t audioBufferSize = 0; static Uint32 audioLastTick = 0; +static unsigned char * shadowAppBuffer = NULL; +static Uint32 shadowAppBufferPos = 0; +static Uint32 shadowAppBufferSize = 0; // Extremely wicked JNI environment to call Java functions from C code static jbyteArray audioBufferJNI = NULL; @@ -144,7 +149,11 @@ static jmethodID JavaResumeAudioPlayback = NULL; static Uint8 *ANDROIDAUD_GetAudioBuf(_THIS) { +#ifdef SDL_AUDIO_APP_IGNORES_RETURNED_BUFFER_SIZE + return(shadowAppBuffer); +#else return(audioBuffer); +#endif } @@ -176,7 +185,7 @@ static int ANDROIDAUD_OpenAudio (_THIS, SDL_AudioSpec *spec) __android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio(): app requested audio bytespersample %d freq %d channels %d samples %d", bytesPerSample, audioFormat->freq, (int)audioFormat->channels, (int)audioFormat->samples); if(audioFormat->samples <= 0) - audioFormat->samples = 128; // Some sane value + audioFormat->samples = 16; // Some sane value if( audioFormat->samples > 32768 ) // Why anyone need so huge audio buffer? { audioFormat->samples = 32768; @@ -185,7 +194,6 @@ static int ANDROIDAUD_OpenAudio (_THIS, SDL_AudioSpec *spec) SDL_CalculateAudioSpec(audioFormat); - (*jniVM)->AttachCurrentThread(jniVM, &jniEnv, NULL); if( !jniEnv ) @@ -209,12 +217,20 @@ static int ANDROIDAUD_OpenAudio (_THIS, SDL_AudioSpec *spec) /* We cannot call DetachCurrentThread() from main thread or we'll crash */ /* (*jniVM)->DetachCurrentThread(jniVM); */ +#ifdef SDL_AUDIO_APP_IGNORES_RETURNED_BUFFER_SIZE + shadowAppBufferSize = audioFormat->size; + shadowAppBuffer = malloc(shadowAppBufferSize); + shadowAppBufferPos = 0; + if( shadowAppBufferSize > audioBufferSize ) + __android_log_print(ANDROID_LOG_FATAL, "libSDL", "ANDROIDAUD_OpenAudio(): Java returned audio buffer smaller than app requested, SDL will crash!"); +#else audioFormat->samples = audioBufferSize / bytesPerSample / audioFormat->channels; audioFormat->size = audioBufferSize; - __android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio(): app opened audio bytespersample %d freq %d channels %d bufsize %d", bytesPerSample, audioFormat->freq, (int)audioFormat->channels, audioBufferSize); +#endif SDL_CalculateAudioSpec(audioFormat); - + __android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio(): app opened audio bytespersample %d freq %d channels %d bufsize %d, SDL returns bufsize %d", bytesPerSample, audioFormat->freq, (int)audioFormat->channels, audioBufferSize, audioFormat->size); + #if SDL_VERSION_ATLEAST(1,3,0) return(1); #else @@ -232,7 +248,10 @@ static void ANDROIDAUD_CloseAudio(_THIS) audioBufferJNI = NULL; audioBuffer = NULL; audioBufferSize = 0; - +#ifdef SDL_AUDIO_APP_IGNORES_RETURNED_BUFFER_SIZE + free(shadowAppBuffer); + shadowAppBuffer = NULL; +#endif (*jniEnv)->CallIntMethod( jniEnv, JavaAudioThread, JavaDeinitAudio ); /* We cannot call DetachCurrentThread() from main thread or we'll crash */ @@ -300,7 +319,7 @@ static void ANDROIDAUD_ThreadDeinit(_THIS) (*jniVM)->DetachCurrentThread(jniVM); }; -static void ANDROIDAUD_PlayAudio(_THIS) +static void ANDROIDAUD_SendAudioToJava(void) { //__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio()"); jboolean isCopy = JNI_TRUE; @@ -318,6 +337,28 @@ static void ANDROIDAUD_PlayAudio(_THIS) __android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio() JNI returns a copy of byte array - that's slow"); } +#ifdef SDL_AUDIO_APP_IGNORES_RETURNED_BUFFER_SIZE +static void ANDROIDAUD_PlayAudio(_THIS) +{ + int audioCopiedSize = MIN(shadowAppBufferSize, audioBufferSize - shadowAppBufferPos); + memcpy(audioBuffer + shadowAppBufferPos, shadowAppBuffer, audioCopiedSize); + shadowAppBufferPos += audioCopiedSize; + if( shadowAppBufferPos >= audioBufferSize ) + { + ANDROIDAUD_SendAudioToJava(); + int audioCopiedRemaining = shadowAppBufferSize - audioCopiedSize; + memcpy(audioBuffer, shadowAppBuffer + audioCopiedSize, audioCopiedRemaining); + shadowAppBufferPos = audioCopiedRemaining; + } +} +#else +static void ANDROIDAUD_PlayAudio(_THIS) +{ + ANDROIDAUD_SendAudioToJava(); +} +#endif + + int SDL_ANDROID_PauseAudioPlayback(void) { JNIEnv * jniEnv = NULL;