From 90dd6953093516fd1425f519e0dd5db544a43ca7 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 3 May 2020 06:54:38 -0700 Subject: [PATCH] Update sound_android for use with rawdrawandroid. --- colorchord2/sound_android.c | 80 ++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/colorchord2/sound_android.c b/colorchord2/sound_android.c index 36a6a4e..6975802 100644 --- a/colorchord2/sound_android.c +++ b/colorchord2/sound_android.c @@ -1,21 +1,36 @@ -//Copyright 2019 <>< Charles Lohr under the ColorChord License. -// NOTE: this does not actually work!!! This driver needs more work!!! It is currently under work. +//Copyright 2019-2020 <>< Charles Lohr under the ColorChord License. +// This should be used with rawdrawandroid #include "sound.h" #include "os_generic.h" -#include "parameters.h" #include //Using android threads not os_generic threads. #include #include #include #include +#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 // for native audio #include #include +#include +#include +#include +#include + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APPNAME, __VA_ARGS__)) +#define printf( x...) LOGI( x ) + #define RECORDER_FRAMES 1024 #define BUFFERSETS 4 @@ -44,20 +59,19 @@ struct SoundDriverAndroid void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { struct SoundDriverAndroid * r = (struct SoundDriverAndroid*)context; - // for streaming recording, here we would call Enqueue to give recorder the next buffer to fill - // but instead, this is a one-time buffer so we stop recording - SLresult result; - result = (*r->recorderRecord)->SetRecordState(r->recorderRecord, SL_RECORDSTATE_STOPPED); - if (SL_RESULT_SUCCESS == result) { - r->recorderSize = 128 * sizeof(short); - } - pthread_mutex_unlock(&audioEngineLock); + int samplesp = 0; + float buffout[RECORDER_FRAMES]; + int i; + short * rb = r->recorderBuffer; + for( i = 0; i < RECORDER_FRAMES; i++ ) buffout[i] = (rb[i]+0.5)/32767.5; + r->callback( 0, buffout, RECORDER_FRAMES, &samplesp, r ); + (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer)); } static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * r ) { SLresult result; - + LOGI( "Starting InitAndroidSound\n" ); // create engine result = slCreateEngine(&r->engineObject, 0, NULL, 0, NULL, NULL); assert(SL_RESULT_SUCCESS == result); @@ -84,9 +98,17 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * // configure audio sink 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, - SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN}; + + SLDataFormat_PCM format_pcm ={ + 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}; // create audio recorder @@ -96,14 +118,14 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * result = (*r->engineEngine)->CreateAudioRecorder(r->engineEngine, &r->recorderObject, &audioSrc, &audioSnk, 1, id, req); if (SL_RESULT_SUCCESS != result) { - printf( "CreateAudioRecorder failed\n" ); + LOGI( "CreateAudioRecorder failed\n" ); return JNI_FALSE; } // realize the audio recorder result = (*r->recorderObject)->Realize(r->recorderObject, SL_BOOLEAN_FALSE); if (SL_RESULT_SUCCESS != result) { - printf( "AudioRecorder Realize failed\n" ); + LOGI( "AudioRecorder Realize failed: %d\n", result ); return JNI_FALSE; } @@ -119,8 +141,7 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * (void)result; // register callback on the buffer queue - result = (*r->recorderBufferQueue)->RegisterCallback(r->recorderBufferQueue, bqRecorderCallback, - NULL); + result = (*r->recorderBufferQueue)->RegisterCallback(r->recorderBufferQueue, bqRecorderCallback, r); assert(SL_RESULT_SUCCESS == result); (void)result; @@ -139,8 +160,7 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * // 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) - result = (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, - RECORDER_FRAMES * sizeof(short)); + result = (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer)); // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, // which for this code example would indicate a programming error assert(SL_RESULT_SUCCESS == result); @@ -151,8 +171,8 @@ static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * assert(SL_RESULT_SUCCESS == result); (void)result; - printf( "Complete Init Sound Android\n" ); - return 0; + LOGI( "Complete Init Sound Android\n" ); + return 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 ) { - printf( "InitSoundAndroid\n" ); + int hasperm = AndroidHasPermissions( "RECORD_AUDIO" ); + if( !hasperm ) + { + AndroidRequestAppPermissions( "RECORD_AUDIO" ); + } + struct SoundDriverAndroid * r = (struct SoundDriverAndroid *)malloc( sizeof( struct SoundDriverAndroid ) ); memset( r, 0, sizeof( *r) ); r->CloseFn = CloseSoundAndroid; @@ -208,5 +238,7 @@ void * InitSoundAndroid( SoundCBType cb ) return InitAndroidSound(r); } +//Tricky: On Android, this can't actually run before main. Have to manually execute it. + REGISTER_SOUND( AndroidSound, 10, "ANDROID", InitSoundAndroid );