diff src/audio/android/SDL_androidaudio.c @ 4995:9f9bea41e88f

Working audio implementation contributed by Joseph Lunderville
author Sam Lantinga <slouken@libsdl.org>
date Thu, 13 Jan 2011 11:14:20 -0800
parents 58b6bb4a45e9
children 8d7315668e35
line wrap: on
line diff
--- a/src/audio/android/SDL_androidaudio.c	Thu Jan 13 09:15:51 2011 -0800
+++ b/src/audio/android/SDL_androidaudio.c	Thu Jan 13 11:14:20 2011 -0800
@@ -18,8 +18,6 @@
 
     Sam Lantinga
     slouken@libsdl.org
-
-    This file written by Ryan C. Gordon (icculus@icculus.org)
 */
 #include "SDL_config.h"
 
@@ -28,18 +26,31 @@
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "SDL_androidaudio.h"
+
 #include "../../SDL_android.h"
 
 #include <android/log.h>
 
+static void * audioDevice;
+
 static int
 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;
     
-    //TODO: Sample rates etc
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Open\n");
+    if (iscapture) {
+    	//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)));
     if (!this->hidden) {
@@ -48,68 +59,78 @@
     }
     SDL_memset(this->hidden, 0, (sizeof *this->hidden));
 
-    while ((!valid_datatype) && (test_format)) {
-        this->spec.format = test_format;
-        switch (test_format) {
-        case AUDIO_S8:
-            /*case AUDIO_S16LSB: */
-            valid_datatype = 1;
-            break;
-        default:
-            test_format = SDL_NextAudioFormat();
+    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;
             break;
         }
+        test_format = SDL_NextAudioFormat();
     }
     
+    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;
 }
 
 static void
 AndroidAUD_PlayDevice(_THIS)
 {
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Play\n");
-    
-
-    //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
+    Android_JNI_WriteAudioBufferAndUnpin();
+    this->hidden->mixbuf = NULL;
 }
 
-
 static Uint8 *
 AndroidAUD_GetDeviceBuf(_THIS)
 {
-     //__android_log_print(ANDROID_LOG_INFO, "SDL", "****** get device buf\n");
-
-     
-    //    sound->data = this->hidden->mixbuf;/* pointer to raw audio data */
-//    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");
+	if (this->hidden->mixbuf == NULL) {
+		this->hidden->mixbuf = Android_JNI_PinAudioBuffer();
+	}
+    return this->hidden->mixbuf;
 }
 
 static void
 AndroidAUD_CloseDevice(_THIS)
 {
-    /* stub */
-     __android_log_print(ANDROID_LOG_INFO, "SDL", "****** close device buf\n");
+    if (this->hidden != NULL) {
+    	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
@@ -118,17 +139,15 @@
     /* Set the function pointers */
     impl->OpenDevice = AndroidAUD_OpenDevice;
     impl->PlayDevice = AndroidAUD_PlayDevice;
-    impl->WaitDevice = AndroidAUD_WaitDevice;
     impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
     impl->CloseDevice = AndroidAUD_CloseDevice;
 
     /* and the capabilities */
+    impl->ProvidesOwnCallbackThread = 1;
     impl->HasCaptureSupport = 0; //TODO
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultInputDevice = 1;
 
-    __android_log_print(ANDROID_LOG_INFO, "SDL","Audio init\n");
-
     return 1;   /* this audio target is available. */
 }
 
@@ -136,4 +155,11 @@
     "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: */