Commit 4f9db82a authored by Sam Lantinga's avatar Sam Lantinga

Working audio implementation contributed by Joseph Lunderville

parent a409f985
...@@ -29,11 +29,15 @@ public class SDLActivity extends Activity { ...@@ -29,11 +29,15 @@ public class SDLActivity extends Activity {
private static SDLSurface mSurface; private static SDLSurface mSurface;
// Audio // Audio
private static Thread mAudioThread;
private static AudioTrack mAudioTrack; private static AudioTrack mAudioTrack;
// Load the .so // Load the .so
static { static {
System.loadLibrary("SDL"); System.loadLibrary("SDL");
//System.loadLibrary("SDL_image");
//System.loadLibrary("SDL_mixer");
//System.loadLibrary("SDL_ttf");
System.loadLibrary("main"); System.loadLibrary("main");
} }
...@@ -67,12 +71,13 @@ public class SDLActivity extends Activity { ...@@ -67,12 +71,13 @@ public class SDLActivity extends Activity {
// C functions we call // C functions we call
public static native void nativeInit(); public static native void nativeInit();
public static native void nativeQuit(); public static native void nativeQuit();
public static native void onNativeResize(int x, int y, int format);
public static native void onNativeKeyDown(int keycode); public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode); public static native void onNativeKeyUp(int keycode);
public static native void onNativeTouch(int action, float x, public static native void onNativeTouch(int action, float x,
float y, float p); float y, float p);
public static native void onNativeResize(int x, int y, int format);
public static native void onNativeAccel(float x, float y, float z); public static native void onNativeAccel(float x, float y, float z);
public static native void nativeRunAudioThread();
// Java functions called from C // Java functions called from C
...@@ -84,23 +89,83 @@ public class SDLActivity extends Activity { ...@@ -84,23 +89,83 @@ public class SDLActivity extends Activity {
mSurface.flipEGL(); mSurface.flipEGL();
} }
public static void updateAudio(byte [] buf) { // Audio
private static Object buf;
public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
// Let the user pick a larger buffer if they really want -- but ye
// gods they probably shouldn't, the minimums are horrifyingly high
// latency already
desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
if(mAudioTrack == null) { audioStartThread();
// Hardcoded things are bad. FIXME when we have more sound stuff
// working properly. Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025, if (is16Bit) {
AudioFormat.CHANNEL_CONFIGURATION_MONO, buf = new short[desiredFrames * (isStereo ? 2 : 1)];
AudioFormat.ENCODING_PCM_8BIT, } else {
2048, buf = new byte[desiredFrames * (isStereo ? 2 : 1)];
AudioTrack.MODE_STREAM); }
return buf;
} }
mAudioTrack.write(buf, 0, buf.length); public static void audioStartThread() {
mAudioThread = new Thread(new Runnable() {
public void run() {
mAudioTrack.play(); mAudioTrack.play();
nativeRunAudioThread();
}
});
Log.v("SDL", "Played some audio"); // I'd take REALTIME if I could get it!
mAudioThread.setPriority(Thread.MAX_PRIORITY);
mAudioThread.start();
}
public static void audioWriteShortBuffer(short[] buffer) {
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(10);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w("SDL", "SDL audio: error return from write(short)");
return;
}
}
}
public static void audioWriteByteBuffer(byte[] buffer) {
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(10);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w("SDL", "SDL audio: error return from write(short)");
return;
}
}
} }
} }
...@@ -279,7 +344,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, ...@@ -279,7 +344,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
} catch(Exception e) { } catch(Exception e) {
Log.v("SDL", e + ""); Log.v("SDL", e + "");
for(StackTraceElement s : e.getStackTrace()) { for (StackTraceElement s : e.getStackTrace()) {
Log.v("SDL", s.toString()); Log.v("SDL", s.toString());
} }
} }
...@@ -303,7 +368,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, ...@@ -303,7 +368,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
} catch(Exception e) { } catch(Exception e) {
Log.v("SDL", "flipEGL(): " + e); Log.v("SDL", "flipEGL(): " + e);
for(StackTraceElement s : e.getStackTrace()) { for (StackTraceElement s : e.getStackTrace()) {
Log.v("SDL", s.toString()); Log.v("SDL", s.toString());
} }
} }
......
...@@ -27,7 +27,10 @@ extern "C" { ...@@ -27,7 +27,10 @@ extern "C" {
#include "events/SDL_events_c.h" #include "events/SDL_events_c.h"
#include "video/android/SDL_androidkeyboard.h" #include "video/android/SDL_androidkeyboard.h"
#include "video/android/SDL_androidvideo.h" #include "video/android/SDL_androidvideo.h"
}
/* Impelemented in audio/android/SDL_androidaudio.c */
extern void Android_RunAudioThread();
} // C
/******************************************************************************* /*******************************************************************************
This file links the Java side of Android with libsdl This file links the Java side of Android with libsdl
...@@ -39,23 +42,21 @@ extern "C" { ...@@ -39,23 +42,21 @@ extern "C" {
/******************************************************************************* /*******************************************************************************
Globals Globals
*******************************************************************************/ *******************************************************************************/
JavaVM* mVM = NULL; static JavaVM* mVM = NULL;
JNIEnv* mEnv = NULL; static JNIEnv* mEnv = NULL;
JNIEnv* mAudioThreadEnv = NULL; //See the note below for why this is necessary static JNIEnv* mAudioEnv = NULL;
//Main activity // Main activity
jclass mActivityInstance; static jclass mActivityInstance;
//method signatures // method signatures
jmethodID midCreateGLContext; static jmethodID midCreateGLContext;
jmethodID midFlipBuffers; static jmethodID midFlipBuffers;
jmethodID midUpdateAudio; static jmethodID midAudioInit;
static jmethodID midAudioWriteShortBuffer;
static jmethodID midAudioWriteByteBuffer;
//Feature IDs // Accelerometer data storage
static const int FEATURE_AUDIO = 1;
static const int FEATURE_ACCEL = 2;
//Accelerometer data storage
float fLastAccelerometer[3]; float fLastAccelerometer[3];
...@@ -82,42 +83,42 @@ extern "C" void SDL_Android_Init(JNIEnv* env) ...@@ -82,42 +83,42 @@ extern "C" void SDL_Android_Init(JNIEnv* env)
mActivityInstance = cls; mActivityInstance = cls;
midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V"); midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V");
midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V"); midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V");
midUpdateAudio = mEnv->GetStaticMethodID(cls,"updateAudio","([B)V"); midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;");
midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V");
midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V");
if(!midCreateGLContext || !midFlipBuffers || !midUpdateAudio) { if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Bad mids\n"); !midAudioWriteShortBuffer || !midAudioWriteByteBuffer) {
} else { __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Good mids\n");
#endif
} }
} }
// Resize
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeResize(
JNIEnv* env, jobject obj,
jint width, jint height, jint format)
{
Android_SetScreenResolution(width, height, format);
}
// Keydown // Keydown
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(JNIEnv* env, extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
jobject obj, jint keycode) JNIEnv* env, jobject obj, jint keycode)
{ {
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native key down %d\n", keycode);
#endif
Android_OnKeyDown(keycode); Android_OnKeyDown(keycode);
} }
// Keyup // Keyup
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(JNIEnv* env, extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
jobject obj, jint keycode) JNIEnv* env, jobject obj, jint keycode)
{ {
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native key up %d\n", keycode);
#endif
Android_OnKeyUp(keycode); Android_OnKeyUp(keycode);
} }
// Touch // Touch
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(JNIEnv* env, extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(
jobject obj, jint action, jfloat x, jfloat y, jfloat p) JNIEnv* env, jobject obj,
jint action, jfloat x, jfloat y, jfloat p)
{ {
#ifdef DEBUG #ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL", __android_log_print(ANDROID_LOG_INFO, "SDL",
...@@ -128,22 +129,7 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(JNIEnv* env, ...@@ -128,22 +129,7 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(JNIEnv* env,
//TODO: Pass this off to the SDL multitouch stuff //TODO: Pass this off to the SDL multitouch stuff
} }
// Quit // Accelerometer
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit( JNIEnv* env,
jobject obj )
{
// Inject a SDL_QUIT event
SDL_SendQuit();
}
// Resize
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeResize(
JNIEnv* env, jobject obj, jint width,
jint height, jint format)
{
Android_SetScreenResolution(width, height, format);
}
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel( extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
JNIEnv* env, jobject obj, JNIEnv* env, jobject obj,
jfloat x, jfloat y, jfloat z) jfloat x, jfloat y, jfloat z)
...@@ -153,6 +139,20 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel( ...@@ -153,6 +139,20 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
fLastAccelerometer[2] = z; fLastAccelerometer[2] = z;
} }
// Quit
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
JNIEnv* env, jobject obj)
{
// Inject a SDL_QUIT event
SDL_SendQuit();
}
extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(
JNIEnv* env)
{
mVM->AttachCurrentThread(&mAudioEnv, NULL);
Android_RunAudioThread();
}
/******************************************************************************* /*******************************************************************************
...@@ -168,33 +168,81 @@ extern "C" void Android_JNI_SwapWindow() ...@@ -168,33 +168,81 @@ extern "C" void Android_JNI_SwapWindow()
mEnv->CallStaticVoidMethod(mActivityInstance, midFlipBuffers); mEnv->CallStaticVoidMethod(mActivityInstance, midFlipBuffers);
} }
extern "C" void Android_JNI_UpdateAudioBuffer(unsigned char *buf, int len) //
// Audio support
//
static jint audioBufferFrames = 0;
static bool audioBuffer16Bit = false;
static bool audioBufferStereo = false;
static jobject audioBuffer;
static void * audioPinnedBuffer;
extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
{ {
//Annoyingly we can't just call into Java from any thread. Because the audio __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
//callback is dispatched from the SDL audio thread (that wasn't made from audioBuffer16Bit = is16Bit;
//java, we have to do some magic here to let the JVM know about the thread. audioBufferStereo = channelCount > 1;
//Because everything it touches on the Java side is static anyway, it's
//not a big deal, just annoying.
if(!mAudioThreadEnv) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Need to set up audio thread env\n");
mVM->AttachCurrentThread(&mAudioThreadEnv, NULL); audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
audioBuffer = mEnv->NewGlobalRef(audioBuffer);
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: ok\n"); if (audioBuffer == NULL) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
return 0;
} }
jbyteArray arr = mAudioThreadEnv->NewByteArray(len); if (audioBufferStereo) {
audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer) / 2;
} else {
audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer);
}
//blah. We probably should rework this so we avoid the copy. return audioBufferFrames;
mAudioThreadEnv->SetByteArrayRegion(arr, 0, len, (jbyte *)buf); }
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: copied\n"); extern "C" void * Android_JNI_PinAudioBuffer()
{
jboolean isCopy = JNI_FALSE;
mAudioThreadEnv->CallStaticVoidMethod( mActivityInstance, if (audioPinnedBuffer != NULL) {
midUpdateAudio, arr ); return audioPinnedBuffer;
}
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: invoked\n"); if (audioBuffer16Bit) {
audioPinnedBuffer = mAudioEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
} else {
audioPinnedBuffer = mAudioEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
}
return audioPinnedBuffer;
}
extern "C" void Android_JNI_WriteAudioBufferAndUnpin()
{
if (audioPinnedBuffer == NULL) {
return;
}
if (audioBuffer16Bit) {
mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioPinnedBuffer, JNI_COMMIT);
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
} else {
mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioPinnedBuffer, JNI_COMMIT);
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
}
audioPinnedBuffer = NULL;
}
extern "C" void Android_JNI_CloseAudioDevice()
{
if (audioBuffer) {
mEnv->DeleteGlobalRef(audioBuffer);
audioBuffer = NULL;
}
// TODO: Implement
} }
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -31,7 +31,12 @@ extern "C" { ...@@ -31,7 +31,12 @@ extern "C" {
/* Interface from the SDL library into the Android Java activity */ /* Interface from the SDL library into the Android Java activity */
void Android_JNI_CreateContext(); void Android_JNI_CreateContext();
void Android_JNI_SwapWindow(); void Android_JNI_SwapWindow();
void Android_JNI_UpdateAudioBuffer(unsigned char *buf, int len);
// Audio support
int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
void* Android_JNI_PinAudioBuffer();
void Android_JNI_WriteAudioBufferAndUnpin();
void Android_JNI_CloseAudioDevice();
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
This file written by Ryan C. Gordon (icculus@icculus.org)
*/ */
#include "SDL_config.h" #include "SDL_config.h"
...@@ -28,18 +26,31 @@ ...@@ -28,18 +26,31 @@
#include "SDL_audio.h" #include "SDL_audio.h"
#include "../SDL_audio_c.h" #include "../SDL_audio_c.h"
#include "SDL_androidaudio.h" #include "SDL_androidaudio.h"
#include "../../SDL_android.h" #include "../../SDL_android.h"
#include <android/log.h> #include <android/log.h>
static void * audioDevice;
static int static int
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
{ {
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); SDL_AudioFormat test_format;
int valid_datatype = 0; int valid_datatype = 0;
//TODO: Sample rates etc if (iscapture) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Open\n"); //TODO: implement capture
SDL_SetError("Capture not supported on Android");
return 0;
}
if (audioDevice != NULL) {
SDL_SetError("Only one audio device at a time please!");
return 0;
}
audioDevice = this;
this->hidden = SDL_malloc(sizeof(*(this->hidden))); this->hidden = SDL_malloc(sizeof(*(this->hidden)));
if (!this->hidden) { if (!this->hidden) {
...@@ -48,17 +59,42 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) ...@@ -48,17 +59,42 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
} }
SDL_memset(this->hidden, 0, (sizeof *this->hidden)); SDL_memset(this->hidden, 0, (sizeof *this->hidden));
while ((!valid_datatype) && (test_format)) { test_format = SDL_FirstAudioFormat(this->spec.format);
while (test_format != 0) { // no "UNKNOWN" constant
if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
this->spec.format = test_format; this->spec.format = test_format;
switch (test_format) {
case AUDIO_S8:
/*case AUDIO_S16LSB: */
valid_datatype = 1;
break; break;
default: }
test_format = SDL_NextAudioFormat(); test_format = SDL_NextAudioFormat();
break;
} }
if (test_format == 0) {
// Didn't find a compatible format :(
SDL_SetError("No compatible audio format!");
return 0;
}
if (this->spec.channels > 1) {
this->spec.channels = 2;
} else {
this->spec.channels = 1;
}
if (this->spec.freq < 8000) {
this->spec.freq = 8000;
}
if (this->spec.freq > 48000) {
this->spec.freq = 48000;
}
// TODO: pass in/return a (Java) device ID, also whether we're opening for input or output
this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
SDL_CalculateAudioSpec(&this->spec);
if (this->spec.samples == 0) {
// Init failed?
SDL_SetError("Java-side initialization failed!");
return 0;
} }
return 1; return 1;
...@@ -67,49 +103,34 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) ...@@ -67,49 +103,34 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
static void static void
AndroidAUD_PlayDevice(_THIS) AndroidAUD_PlayDevice(_THIS)
{ {
__android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Play\n"); Android_JNI_WriteAudioBufferAndUnpin();
this->hidden->mixbuf = NULL;
//playGenericSound(this->hidden->mixbuf, this->hidden->mixlen);
#if 0
// sound->rate = 22050; /* sample rate = 22050Hz */
// sound->vol = 127; /* volume [0..127] for [min..max] */
// sound->pan = 64; /* balance [0..127] for [left..right] */
// sound->format = 0; /* 0 for 16-bit, 1 for 8-bit */
// playSound(sound);
#endif
} }
static Uint8 * static Uint8 *
AndroidAUD_GetDeviceBuf(_THIS) AndroidAUD_GetDeviceBuf(_THIS)
{ {
//__android_log_print(ANDROID_LOG_INFO, "SDL", "****** get device buf\n"); if (this->hidden->mixbuf == NULL) {
this->hidden->mixbuf = Android_JNI_PinAudioBuffer();
}
// sound->data = this->hidden->mixbuf;/* pointer to raw audio data */ return this->hidden->mixbuf;
// sound->len = this->hidden->mixlen; /* size of raw data pointed to above */
Android_JNI_UpdateAudioBuffer(this->hidden->mixbuf, this->hidden->mixlen);
return this->hidden->mixbuf; /* is this right? */
}
static void
AndroidAUD_WaitDevice(_THIS)
{
/* stub */
__android_log_print(ANDROID_LOG_INFO, "SDL", "****** wait device buf\n");
} }
static void static void
AndroidAUD_CloseDevice(_THIS) AndroidAUD_CloseDevice(_THIS)
{ {
/* stub */ if (this->hidden != NULL) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "****** close device buf\n"); if (this->hidden->mixbuf != NULL) {
Android_JNI_WriteAudioBufferAndUnpin();
}
SDL_free(this->hidden);
this->hidden = NULL;
}
Android_JNI_CloseAudioDevice();
if (audioDevice == this) {
audioDevice = NULL;
}
} }
static int static int
...@@ -118,17 +139,15 @@ AndroidAUD_Init(SDL_AudioDriverImpl * impl) ...@@ -118,17 +139,15 @@ AndroidAUD_Init(SDL_AudioDriverImpl * impl)
/* Set the function pointers */ /* Set the function pointers */
impl->OpenDevice = AndroidAUD_OpenDevice; impl->OpenDevice = AndroidAUD_OpenDevice;
impl->PlayDevice = AndroidAUD_PlayDevice; impl->PlayDevice = AndroidAUD_PlayDevice;
impl->WaitDevice = AndroidAUD_WaitDevice;
impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf; impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
impl->CloseDevice = AndroidAUD_CloseDevice; impl->CloseDevice = AndroidAUD_CloseDevice;
/* and the capabilities */ /* and the capabilities */
impl->ProvidesOwnCallbackThread = 1;
impl->HasCaptureSupport = 0; //TODO impl->HasCaptureSupport = 0; //TODO
impl->OnlyHasDefaultOutputDevice = 1; impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultInputDevice = 1; impl->OnlyHasDefaultInputDevice = 1;
__android_log_print(ANDROID_LOG_INFO, "SDL","Audio init\n");
return 1; /* this audio target is available. */ return 1; /* this audio target is available. */
} }
...@@ -136,4 +155,11 @@ AudioBootStrap ANDROIDAUD_bootstrap = { ...@@ -136,4 +155,11 @@ AudioBootStrap ANDROIDAUD_bootstrap = {
"android", "SDL Android audio driver", AndroidAUD_Init, 0 /*1? */ "android", "SDL Android audio driver", AndroidAUD_Init, 0 /*1? */
}; };
/* Called by the Java code to start the audio processing on a thread */
void
Android_RunAudioThread()
{
SDL_RunAudio(audioDevice);
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -34,9 +34,8 @@ struct SDL_PrivateAudioData ...@@ -34,9 +34,8 @@ struct SDL_PrivateAudioData
/* The file descriptor for the audio device */ /* The file descriptor for the audio device */
Uint8 *mixbuf; Uint8 *mixbuf;
Uint32 mixlen; Uint32 mixlen;
Uint32 write_delay;
Uint32 initial_calls;
}; };
#endif /* _SDL_androidaudio_h */ #endif /* _SDL_androidaudio_h */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment