Update sound_android for use with rawdrawandroid.
This commit is contained in:
parent
03c938b453
commit
90dd695309
|
@ -1,21 +1,36 @@
|
||||||
//Copyright 2019 <>< Charles Lohr under the ColorChord License.
|
//Copyright 2019-2020 <>< Charles Lohr under the ColorChord License.
|
||||||
// NOTE: this does not actually work!!! This driver needs more work!!! It is currently under work.
|
// This should be used with rawdrawandroid
|
||||||
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "os_generic.h"
|
#include "os_generic.h"
|
||||||
#include "parameters.h"
|
|
||||||
#include <pthread.h> //Using android threads not os_generic threads.
|
#include <pthread.h> //Using android threads not os_generic threads.
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef NO_SOUND_PARAMETERS
|
||||||
|
#include "parameters.h"
|
||||||
|
#else
|
||||||
|
#define GetParameterI( x, y ) (y)
|
||||||
|
#define GetParameterS( x, y ) (y)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//based on https://github.com/android/ndk-samples/blob/master/native-audio/app/src/main/cpp/native-audio-jni.c
|
//based on https://github.com/android/ndk-samples/blob/master/native-audio/app/src/main/cpp/native-audio-jni.c
|
||||||
|
|
||||||
// for native audio
|
// for native audio
|
||||||
#include <SLES/OpenSLES.h>
|
#include <SLES/OpenSLES.h>
|
||||||
#include <SLES/OpenSLES_Android.h>
|
#include <SLES/OpenSLES_Android.h>
|
||||||
|
|
||||||
|
#include <android_native_app_glue.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <native_activity.h>
|
||||||
|
|
||||||
|
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APPNAME, __VA_ARGS__))
|
||||||
|
#define printf( x...) LOGI( x )
|
||||||
|
|
||||||
#define RECORDER_FRAMES 1024
|
#define RECORDER_FRAMES 1024
|
||||||
|
|
||||||
#define BUFFERSETS 4
|
#define BUFFERSETS 4
|
||||||
|
@ -44,20 +59,19 @@ struct SoundDriverAndroid
|
||||||
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||||
{
|
{
|
||||||
struct SoundDriverAndroid * r = (struct SoundDriverAndroid*)context;
|
struct SoundDriverAndroid * r = (struct SoundDriverAndroid*)context;
|
||||||
// for streaming recording, here we would call Enqueue to give recorder the next buffer to fill
|
int samplesp = 0;
|
||||||
// but instead, this is a one-time buffer so we stop recording
|
float buffout[RECORDER_FRAMES];
|
||||||
SLresult result;
|
int i;
|
||||||
result = (*r->recorderRecord)->SetRecordState(r->recorderRecord, SL_RECORDSTATE_STOPPED);
|
short * rb = r->recorderBuffer;
|
||||||
if (SL_RESULT_SUCCESS == result) {
|
for( i = 0; i < RECORDER_FRAMES; i++ ) buffout[i] = (rb[i]+0.5)/32767.5;
|
||||||
r->recorderSize = 128 * sizeof(short);
|
r->callback( 0, buffout, RECORDER_FRAMES, &samplesp, r );
|
||||||
}
|
(*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer));
|
||||||
pthread_mutex_unlock(&audioEngineLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * r )
|
static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * r )
|
||||||
{
|
{
|
||||||
SLresult result;
|
SLresult result;
|
||||||
|
LOGI( "Starting InitAndroidSound\n" );
|
||||||
// create engine
|
// create engine
|
||||||
result = slCreateEngine(&r->engineObject, 0, NULL, 0, NULL, NULL);
|
result = slCreateEngine(&r->engineObject, 0, NULL, 0, NULL, NULL);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
@ -84,9 +98,17 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid *
|
||||||
|
|
||||||
// configure audio sink
|
// configure audio sink
|
||||||
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||||
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_16,
|
|
||||||
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
SLDataFormat_PCM format_pcm ={
|
||||||
SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
|
SL_DATAFORMAT_PCM,
|
||||||
|
1,
|
||||||
|
SL_SAMPLINGRATE_16,
|
||||||
|
SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||||
|
SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||||
|
SL_SPEAKER_FRONT_CENTER,
|
||||||
|
SL_BYTEORDER_LITTLEENDIAN,
|
||||||
|
};
|
||||||
|
|
||||||
SLDataSink audioSnk = {&loc_bq, &format_pcm};
|
SLDataSink audioSnk = {&loc_bq, &format_pcm};
|
||||||
|
|
||||||
// create audio recorder
|
// create audio recorder
|
||||||
|
@ -96,14 +118,14 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid *
|
||||||
result = (*r->engineEngine)->CreateAudioRecorder(r->engineEngine, &r->recorderObject, &audioSrc,
|
result = (*r->engineEngine)->CreateAudioRecorder(r->engineEngine, &r->recorderObject, &audioSrc,
|
||||||
&audioSnk, 1, id, req);
|
&audioSnk, 1, id, req);
|
||||||
if (SL_RESULT_SUCCESS != result) {
|
if (SL_RESULT_SUCCESS != result) {
|
||||||
printf( "CreateAudioRecorder failed\n" );
|
LOGI( "CreateAudioRecorder failed\n" );
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// realize the audio recorder
|
// realize the audio recorder
|
||||||
result = (*r->recorderObject)->Realize(r->recorderObject, SL_BOOLEAN_FALSE);
|
result = (*r->recorderObject)->Realize(r->recorderObject, SL_BOOLEAN_FALSE);
|
||||||
if (SL_RESULT_SUCCESS != result) {
|
if (SL_RESULT_SUCCESS != result) {
|
||||||
printf( "AudioRecorder Realize failed\n" );
|
LOGI( "AudioRecorder Realize failed: %d\n", result );
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +141,7 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid *
|
||||||
(void)result;
|
(void)result;
|
||||||
|
|
||||||
// register callback on the buffer queue
|
// register callback on the buffer queue
|
||||||
result = (*r->recorderBufferQueue)->RegisterCallback(r->recorderBufferQueue, bqRecorderCallback,
|
result = (*r->recorderBufferQueue)->RegisterCallback(r->recorderBufferQueue, bqRecorderCallback, r);
|
||||||
NULL);
|
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
(void)result;
|
(void)result;
|
||||||
|
|
||||||
|
@ -139,8 +160,7 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid *
|
||||||
|
|
||||||
// enqueue an empty buffer to be filled by the recorder
|
// enqueue an empty buffer to be filled by the recorder
|
||||||
// (for streaming recording, we would enqueue at least 2 empty buffers to start things off)
|
// (for streaming recording, we would enqueue at least 2 empty buffers to start things off)
|
||||||
result = (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer,
|
result = (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer));
|
||||||
RECORDER_FRAMES * sizeof(short));
|
|
||||||
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
|
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
|
||||||
// which for this code example would indicate a programming error
|
// which for this code example would indicate a programming error
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
@ -151,8 +171,8 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid *
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
(void)result;
|
(void)result;
|
||||||
|
|
||||||
printf( "Complete Init Sound Android\n" );
|
LOGI( "Complete Init Sound Android\n" );
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloseSoundAndroid( struct SoundDriverAndroid * r );
|
void CloseSoundAndroid( struct SoundDriverAndroid * r );
|
||||||
|
@ -182,9 +202,19 @@ void CloseSoundAndroid( struct SoundDriverAndroid * r )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int AndroidHasPermissions(const char* perm_name);
|
||||||
|
void AndroidRequestAppPermissions(const char * perm);
|
||||||
|
|
||||||
|
|
||||||
void * InitSoundAndroid( SoundCBType cb )
|
void * InitSoundAndroid( SoundCBType cb )
|
||||||
{
|
{
|
||||||
printf( "InitSoundAndroid\n" );
|
int hasperm = AndroidHasPermissions( "RECORD_AUDIO" );
|
||||||
|
if( !hasperm )
|
||||||
|
{
|
||||||
|
AndroidRequestAppPermissions( "RECORD_AUDIO" );
|
||||||
|
}
|
||||||
|
|
||||||
struct SoundDriverAndroid * r = (struct SoundDriverAndroid *)malloc( sizeof( struct SoundDriverAndroid ) );
|
struct SoundDriverAndroid * r = (struct SoundDriverAndroid *)malloc( sizeof( struct SoundDriverAndroid ) );
|
||||||
memset( r, 0, sizeof( *r) );
|
memset( r, 0, sizeof( *r) );
|
||||||
r->CloseFn = CloseSoundAndroid;
|
r->CloseFn = CloseSoundAndroid;
|
||||||
|
@ -208,5 +238,7 @@ void * InitSoundAndroid( SoundCBType cb )
|
||||||
return InitAndroidSound(r);
|
return InitAndroidSound(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Tricky: On Android, this can't actually run before main. Have to manually execute it.
|
||||||
|
|
||||||
REGISTER_SOUND( AndroidSound, 10, "ANDROID", InitSoundAndroid );
|
REGISTER_SOUND( AndroidSound, 10, "ANDROID", InitSoundAndroid );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue