engine/engine/client/snd_droid.c

155 lines
4.1 KiB
C

/*
this file is basically a copy of the SDL one
java code has a function or two which just periodically calls us to ask us to dump out audio for it
*/
#include "quakedef.h"
#include <jni.h>
#include <pthread.h>
static soundcardinfo_t *sys_sc = NULL;
extern int sys_soundflags;
//called by the java code when it wants to know what sort of AudioTrack format to use.
JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_audioinfo(JNIEnv *env, jclass this, jint arg)
{
soundcardinfo_t *sc = sys_sc;
if (!sc)
return 0;
switch(arg)
{
case 1:
return sc->sn.numchannels;
case 2:
return sc->sn.samplebytes*8;
default:
return sc->sn.speed;
}
}
extern int S_GetMixerTime(soundcardinfo_t *sc);
//transfer the 'dma' buffer into the buffer it requests, called from a dedicated sound thread created by the java code.
JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_paintaudio(JNIEnv *env, jclass this, jbyteArray stream, jint len)
{
int offset = 0;
soundcardinfo_t *sc = sys_sc;
int framesz;
if (sc)
{
int buffersize = sc->sn.samples*sc->sn.samplebytes;
int curtime = S_GetMixerTime(sc);
framesz = sc->sn.numchannels * sc->sn.samplebytes;
S_PaintChannels (sc, curtime + (len / framesz));
if (len > buffersize)
{
len = buffersize; //whoa nellie!
}
if (len + sc->snd_sent%buffersize > buffersize)
{ //buffer will wrap, fill in the rest
(*env)->SetByteArrayRegion(env, stream, offset, buffersize - (sc->snd_sent%buffersize), (char*)sc->sn.buffer + (sc->snd_sent%buffersize));
offset += buffersize - (sc->snd_sent%buffersize);
sc->snd_sent += buffersize - (sc->snd_sent%buffersize);
len -= buffersize - (sc->snd_sent%buffersize);
if (len < 0) /*this must be impossible, surely?*/
len = 0;
}
//and finish from the start
(*env)->SetByteArrayRegion(env, stream, offset, len, (char*)sc->sn.buffer + (sc->snd_sent%buffersize));
offset += len;
sc->snd_sent += len;
}
else
offset = len; /*so the playback thread ends up blocked properly*/
return offset;
}
static void Droid_Shutdown(soundcardinfo_t *sc)
{
//fixme: what if we're currently inside Java_com_fteqw_FTEDroidEngine_paintaudio?
sys_sc = NULL;
free(sc->sn.buffer);
sys_soundflags = 0;
}
//return the number of samples that have already been submitted to the device.
static unsigned int Droid_GetDMAPos(soundcardinfo_t *sc)
{
sc->sn.samplepos = sc->snd_sent / sc->sn.samplebytes;
return sc->sn.samplepos;
}
static void Droid_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{
}
static void *Droid_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{
return sc->sn.buffer;
}
/*
static void Droid_SetEnvironmentReverb(soundcardinfo_t *sc, qboolean uw)
{
}
*/
static void Droid_Submit(soundcardinfo_t *sc, int start, int end)
{
}
//on android, 16bit audio is 'guarenteed'.
//8bit is not guarenteed.
//there's no reference to sample rates. I assume 44.1khz will always work, though we want to avoid that cpu+mem load if we can
//nor any guarentee about channels supported. I assume mono will always work.
static qboolean Droid_InitCard (soundcardinfo_t *sc, const char *cardname)
{
if (sys_sc)
return false; //can only cope with one device.
if (cardname && *cardname)
return false; //only the default device
sc->selfpainting = true;
// sc->sn.speed = 11025;
// sc->sn.samplebytes = 2;
// sc->sn.numchannels = 1;
if (sc->sn.samplebytes == 1)
sc->sn.sampleformat = QSF_U8;
else /*if (sc->sn.samplebytes == 2)*/
{
sc->sn.samplebytes = 2;
sc->sn.sampleformat = QSF_S16;
}
/*internal buffer should have 1 sec audio*/
sc->sn.samples = sc->sn.speed*sc->sn.numchannels;
sc->Lock = Droid_LockBuffer;
sc->Unlock = Droid_UnlockBuffer;
// sc->SetEnvironmentReverb = Droid_SetEnvironmentReverb;
sc->Submit = Droid_Submit;
sc->Shutdown = Droid_Shutdown;
sc->GetDMAPos = Droid_GetDMAPos;
sc->sn.buffer = malloc(sc->sn.samples*sc->sn.samplebytes);
sys_sc = sc;
sys_soundflags = 3;
return 1;
}
sounddriver_t Droid_AudioOutput =
{
"Android",
Droid_InitCard,
NULL
};