mirror of
https://github.com/jamessanford/kegs.git
synced 2024-06-13 08:29:35 +00:00
First pass at OpenSLES audio driver.
This commit is contained in:
parent
b5fbd12a26
commit
91f006be3a
|
@ -3,7 +3,7 @@
|
|||
package="com.froop.app.kegs"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />
|
||||
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="16" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
|
|
|
@ -7,7 +7,7 @@ LOCAL_MODULE := kegs
|
|||
LOCAL_SRC_FILES := adb.c clock.c config.c dis.c engine_c.c scc.c iwm.c \
|
||||
joystick_driver.c moremem.c paddles.c sim65816.c smartport.c \
|
||||
sound.c sound_driver.c video.c scc_socket_driver.c scc_windriver.c \
|
||||
scc_macdriver.c android_driver.c
|
||||
LOCAL_LDLIBS := -lm -llog -ljnigraphics
|
||||
scc_macdriver.c android_driver.c android_sound_driver.c
|
||||
LOCAL_LDLIBS := -lm -llog -ljnigraphics -lOpenSLES
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# The ARMv7 is significanly faster due to the use of the hardware FPU
|
||||
APP_ABI := armeabi armeabi-v7a
|
||||
#APP_ABI := armeabi-v7a
|
||||
APP_PLATFORM := android-8
|
||||
APP_PLATFORM := android-9
|
||||
|
|
162
jni/android_sound_driver.c
Normal file
162
jni/android_sound_driver.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
// Lots of boilerplate OpenSLES code from the Android NDK 'native-audio' sample.
|
||||
// Hooked up to a copy of the KEGS Mac sound driver.
|
||||
|
||||
#include <assert.h>
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOG_TAG "libkegs"
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
#include <SLES/OpenSLES.h>
|
||||
#include <SLES/OpenSLES_Android.h>
|
||||
|
||||
#include "defc.h"
|
||||
#include "sound.h"
|
||||
|
||||
extern JNIEnv *g_env;
|
||||
extern jobject g_thiz;
|
||||
|
||||
extern int g_audio_rate;
|
||||
extern int g_audio_socket;
|
||||
extern int g_audio_enable;
|
||||
|
||||
static SLObjectItf engineObject = NULL;
|
||||
static SLEngineItf engineEngine;
|
||||
static SLObjectItf outputMixObject = NULL;
|
||||
|
||||
static SLObjectItf bqPlayerObject = NULL;
|
||||
static SLPlayItf bqPlayerPlay;
|
||||
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
|
||||
static SLVolumeItf bqPlayerVolume;
|
||||
|
||||
#define MACSND_REBUF_SIZE (64*1024)
|
||||
#define MACSND_QUANTA 512
|
||||
/* MACSND_QUANTA must be >= 128 and a power of 2 */
|
||||
|
||||
word32 g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
volatile word32 *g_macsnd_rebuf_ptr;
|
||||
volatile word32 *g_macsnd_rebuf_cur;
|
||||
volatile int g_macsnd_playing = 0;
|
||||
|
||||
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
{
|
||||
int samps;
|
||||
assert(bq == bqPlayerBufferQueue);
|
||||
assert(NULL == context);
|
||||
|
||||
samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur;
|
||||
if(samps < 0) {
|
||||
samps += MACSND_REBUF_SIZE;
|
||||
}
|
||||
samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples
|
||||
if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) - g_macsnd_rebuf_cur;
|
||||
}
|
||||
if(samps > 0) {
|
||||
g_macsnd_playing = 1;
|
||||
|
||||
SLresult result;
|
||||
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, (char *)g_macsnd_rebuf_cur, samps * 4);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
g_macsnd_rebuf_cur += samps;
|
||||
if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE;
|
||||
}
|
||||
} else {
|
||||
g_macsnd_playing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int android_send_audio(byte *ptr, int in_size) {
|
||||
word32 *wptr, *macptr;
|
||||
word32 *eptr;
|
||||
int samps;
|
||||
int i;
|
||||
|
||||
samps = in_size / 4;
|
||||
wptr = (word32 *)ptr;
|
||||
macptr = (word32 *)g_macsnd_rebuf_ptr;
|
||||
eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
for(i = 0; i < samps; i++) {
|
||||
*macptr++ = *wptr++;
|
||||
if(macptr >= eptr) {
|
||||
macptr = &g_macsnd_rebuf[0];
|
||||
}
|
||||
}
|
||||
|
||||
g_macsnd_rebuf_ptr = macptr;
|
||||
|
||||
if(!g_macsnd_playing) {
|
||||
bqPlayerCallback(bqPlayerBufferQueue, NULL);
|
||||
}
|
||||
|
||||
return in_size;
|
||||
}
|
||||
|
||||
void child_sound_init_android() {
|
||||
g_audio_rate = 44100;
|
||||
set_audio_rate(g_audio_rate);
|
||||
|
||||
SLresult result;
|
||||
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 2, SL_SAMPLINGRATE_44_1,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN};
|
||||
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
||||
|
||||
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
|
||||
SLDataSink audioSnk = {&loc_outmix, NULL};
|
||||
|
||||
const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
|
||||
const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
|
||||
&bqPlayerBufferQueue);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
|
||||
// -1000 is listenable, -2000 is quiet, ...
|
||||
#if 0
|
||||
result = (*bqPlayerVolume)->SetVolumeLevel(bqPlayerVolume, -2000);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
#endif
|
||||
|
||||
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
}
|
||||
|
||||
void android_snd_init(word32 *shmaddr) {
|
||||
g_macsnd_rebuf_cur = &g_macsnd_rebuf[0];
|
||||
g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0];
|
||||
|
||||
/* just initialization, results in child_sound_init_android() */
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
}
|
22
jni/sound.c
22
jni/sound.c
|
@ -45,7 +45,7 @@ int g_queued_samps = 0;
|
|||
int g_queued_nonsamps = 0;
|
||||
int g_num_osc_interrupting = 0;
|
||||
|
||||
#if defined(HPUX) || (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32) || defined(MAC)
|
||||
#if defined(HPUX) || defined(__linux__) || defined(_WIN32) || defined(MAC) || defined(__ANDROID__)
|
||||
int g_audio_enable = -1;
|
||||
#else
|
||||
# if defined(OSS)
|
||||
|
@ -344,16 +344,16 @@ sound_init_general()
|
|||
}
|
||||
|
||||
parent_sound_get_sample_rate(g_pipe2_fd[0]);
|
||||
#else
|
||||
# ifdef MAC
|
||||
#endif
|
||||
#ifdef MAC
|
||||
macsnd_init(shmaddr);
|
||||
# else
|
||||
# if !defined(__ANDROID__)
|
||||
/* windows */
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
android_snd_init(shmaddr);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
win32snd_init(shmaddr);
|
||||
# endif
|
||||
# endif
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -598,7 +598,7 @@ send_sound(int real_samps, int size)
|
|||
DOC_LOG("send_sound", -1, g_last_sound_play_dsamp,
|
||||
(real_samps << 30) + size);
|
||||
|
||||
#if defined(MAC) || defined(_WIN32)
|
||||
#if defined(MAC) || defined(_WIN32) || defined(__ANDROID__)
|
||||
ret = 0;
|
||||
child_sound_playit(tmp);
|
||||
#else
|
||||
|
@ -1011,7 +1011,7 @@ sound_play(double dsamps)
|
|||
|
||||
outptr += 2;
|
||||
|
||||
#if (defined(__linux__) && !defined(__ANDROID__)) || defined(OSS)
|
||||
#if defined(__linux__) || defined(OSS)
|
||||
/* Linux seems to expect little-endian */
|
||||
/* samples always, even on PowerPC */
|
||||
# ifdef KEGS_LITTLE_ENDIAN
|
||||
|
|
|
@ -75,12 +75,15 @@ reliable_buf_write(word32 *shm_addr, int pos, int size)
|
|||
while(size > 0) {
|
||||
#ifdef _WIN32
|
||||
ret = win32_send_audio(ptr, size);
|
||||
#else
|
||||
# ifdef MAC
|
||||
#endif
|
||||
#ifdef MAC
|
||||
ret = mac_send_audio(ptr, size);
|
||||
# else
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
ret = android_send_audio(ptr, size);
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(MAC) && !defined(__ANDROID__)
|
||||
ret = write(g_audio_socket, ptr, size);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if(ret < 0) {
|
||||
|
@ -128,10 +131,6 @@ child_sound_loop(int read_fd, int write_fd, word32 *shm_addr)
|
|||
g_childsnd_vbl = 0;
|
||||
g_childsnd_shm_addr = shm_addr;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef HPUX
|
||||
child_sound_init_hpdev();
|
||||
#endif
|
||||
|
@ -146,6 +145,10 @@ child_sound_loop(int read_fd, int write_fd, word32 *shm_addr)
|
|||
child_sound_init_mac();
|
||||
return;
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
child_sound_init_android();
|
||||
return;
|
||||
#endif
|
||||
|
||||
tmp = g_audio_rate;
|
||||
ret = write(write_fd, &tmp, 4);
|
||||
|
|
Loading…
Reference in New Issue
Block a user