Implement Audio Input support on Android
This commit is contained in:
parent
ce615c1a82
commit
29fb6b4e15
2 changed files with 119 additions and 0 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue