diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2019-03-01 08:51:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-01 08:51:00 +0100 |
commit | 482dcf526653299a068741baad91965f83506ac1 (patch) | |
tree | 0009b28b491bf554f74894d3e1bcaba11daf6f78 | |
parent | 8d117b214f2bcd14015532fdfbed9b3f059da0e6 (diff) | |
parent | 29fb6b4e152f937edad5512561dfd7629e167de8 (diff) |
Merge pull request #26407 from marcelofg55/audio_input_android
Implement Audio Input support on Android
-rw-r--r-- | platform/android/audio_driver_opensl.cpp | 104 | ||||
-rw-r--r-- | platform/android/audio_driver_opensl.h | 15 |
2 files changed, 119 insertions, 0 deletions
diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp index e259380a63..0d62b242a8 100644 --- a/platform/android/audio_driver_opensl.cpp +++ b/platform/android/audio_driver_opensl.cpp @@ -211,6 +211,110 @@ void AudioDriverOpenSL::start() { active = true; } +void AudioDriverOpenSL::_record_buffer_callback(SLAndroidSimpleBufferQueueItf queueItf) { + + for (int i = 0; i < rec_buffer.size(); i++) { + int32_t sample = rec_buffer[i] << 16; + input_buffer_write(sample); + input_buffer_write(sample); // call twice to convert to Stereo + } + + SLresult res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); + ERR_FAIL_COND(res != SL_RESULT_SUCCESS); +} + +void AudioDriverOpenSL::_record_buffer_callbacks(SLAndroidSimpleBufferQueueItf queueItf, void *pContext) { + + AudioDriverOpenSL *ad = (AudioDriverOpenSL *)pContext; + + ad->_record_buffer_callback(queueItf); +} + +Error AudioDriverOpenSL::capture_start() { + + SLDataLocator_IODevice loc_dev = { + SL_DATALOCATOR_IODEVICE, + SL_IODEVICE_AUDIOINPUT, + SL_DEFAULTDEVICEID_AUDIOINPUT, + NULL + }; + SLDataSource recSource = { &loc_dev, NULL }; + + SLDataLocator_AndroidSimpleBufferQueue loc_bq = { + SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, + 2 + }; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 1, + SL_SAMPLINGRATE_44_1, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_CENTER, + SL_BYTEORDER_LITTLEENDIAN + }; + SLDataSink recSnk = { &loc_bq, &format_pcm }; + + const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; + const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; + + SLresult res = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recSnk, 2, ids, req); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recorder)->GetInterface(recorder, SL_IID_RECORD, (void *)&recordItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void *)&recordBufferQueueItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordBufferQueueItf)->RegisterCallback(recordBufferQueueItf, _record_buffer_callbacks, this); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + SLuint32 state; + res = (*recordItf)->GetRecordState(recordItf, &state); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + if (state != SL_RECORDSTATE_STOPPED) { + res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + } + + const int rec_buffer_frames = 2048; + rec_buffer.resize(rec_buffer_frames); + input_buffer_init(rec_buffer_frames); + + res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + return OK; +} + +Error AudioDriverOpenSL::capture_stop() { + + SLuint32 state; + SLresult res = (*recordItf)->GetRecordState(recordItf, &state); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + if (state != SL_RECORDSTATE_STOPPED) { + res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + } + + return OK; +} + int AudioDriverOpenSL::get_mix_rate() const { return 44100; diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h index 77e16e507a..9bd0d5e999 100644 --- a/platform/android/audio_driver_opensl.h +++ b/platform/android/audio_driver_opensl.h @@ -54,13 +54,18 @@ class AudioDriverOpenSL : public AudioDriver { int32_t *mixdown_buffer; int last_free; + Vector<int16_t> rec_buffer; + SLPlayItf playItf; + SLRecordItf recordItf; SLObjectItf sl; SLEngineItf EngineItf; SLObjectItf OutputMix; SLVolumeItf volumeItf; SLObjectItf player; + SLObjectItf recorder; SLAndroidSimpleBufferQueueItf bufferQueueItf; + SLAndroidSimpleBufferQueueItf recordBufferQueueItf; SLDataSource audioSource; SLDataFormat_PCM pcm; SLDataSink audioSink; @@ -76,6 +81,13 @@ class AudioDriverOpenSL : public AudioDriver { SLAndroidSimpleBufferQueueItf queueItf, void *pContext); + void _record_buffer_callback( + SLAndroidSimpleBufferQueueItf queueItf); + + static void _record_buffer_callbacks( + SLAndroidSimpleBufferQueueItf queueItf, + void *pContext); + public: void set_singleton(); @@ -91,6 +103,9 @@ public: virtual void set_pause(bool p_pause); + virtual Error capture_start(); + virtual Error capture_stop(); + AudioDriverOpenSL(); }; |