You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Implement Audio Input support on Android
This commit is contained in:
@@ -211,6 +211,110 @@ void AudioDriverOpenSL::start() {
|
|||||||
active = true;
|
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 {
|
int AudioDriverOpenSL::get_mix_rate() const {
|
||||||
|
|
||||||
return 44100;
|
return 44100;
|
||||||
|
|||||||
@@ -54,13 +54,18 @@ class AudioDriverOpenSL : public AudioDriver {
|
|||||||
int32_t *mixdown_buffer;
|
int32_t *mixdown_buffer;
|
||||||
int last_free;
|
int last_free;
|
||||||
|
|
||||||
|
Vector<int16_t> rec_buffer;
|
||||||
|
|
||||||
SLPlayItf playItf;
|
SLPlayItf playItf;
|
||||||
|
SLRecordItf recordItf;
|
||||||
SLObjectItf sl;
|
SLObjectItf sl;
|
||||||
SLEngineItf EngineItf;
|
SLEngineItf EngineItf;
|
||||||
SLObjectItf OutputMix;
|
SLObjectItf OutputMix;
|
||||||
SLVolumeItf volumeItf;
|
SLVolumeItf volumeItf;
|
||||||
SLObjectItf player;
|
SLObjectItf player;
|
||||||
|
SLObjectItf recorder;
|
||||||
SLAndroidSimpleBufferQueueItf bufferQueueItf;
|
SLAndroidSimpleBufferQueueItf bufferQueueItf;
|
||||||
|
SLAndroidSimpleBufferQueueItf recordBufferQueueItf;
|
||||||
SLDataSource audioSource;
|
SLDataSource audioSource;
|
||||||
SLDataFormat_PCM pcm;
|
SLDataFormat_PCM pcm;
|
||||||
SLDataSink audioSink;
|
SLDataSink audioSink;
|
||||||
@@ -76,6 +81,13 @@ class AudioDriverOpenSL : public AudioDriver {
|
|||||||
SLAndroidSimpleBufferQueueItf queueItf,
|
SLAndroidSimpleBufferQueueItf queueItf,
|
||||||
void *pContext);
|
void *pContext);
|
||||||
|
|
||||||
|
void _record_buffer_callback(
|
||||||
|
SLAndroidSimpleBufferQueueItf queueItf);
|
||||||
|
|
||||||
|
static void _record_buffer_callbacks(
|
||||||
|
SLAndroidSimpleBufferQueueItf queueItf,
|
||||||
|
void *pContext);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_singleton();
|
void set_singleton();
|
||||||
|
|
||||||
@@ -91,6 +103,9 @@ public:
|
|||||||
|
|
||||||
virtual void set_pause(bool p_pause);
|
virtual void set_pause(bool p_pause);
|
||||||
|
|
||||||
|
virtual Error capture_start();
|
||||||
|
virtual Error capture_stop();
|
||||||
|
|
||||||
AudioDriverOpenSL();
|
AudioDriverOpenSL();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user