diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cubeb-jni.cpp | 16 | ||||
-rw-r--r-- | src/cubeb-jni.h | 2 | ||||
-rw-r--r-- | src/cubeb_aaudio.cpp | 108 |
3 files changed, 118 insertions, 8 deletions
diff --git a/src/cubeb-jni.cpp b/src/cubeb-jni.cpp index 57c642d..064835d 100644 --- a/src/cubeb-jni.cpp +++ b/src/cubeb-jni.cpp @@ -125,6 +125,22 @@ cubeb_jni_init() return cubeb_jni_ptr; } +extern "C" const char * +cubeb_fx_type_description(cubeb_fx_type type) +{ + switch (type) { + case CUBEB_FX_ACOUSTIC_ECHO_CANCELER: + return "CUBEB_FX_ACOUSTIC_ECHO_CANCELER"; + case CUBEB_FX_AUTOMATIC_GAIN_CONTROL: + return "CUBEB_FX_AUTOMATIC_GAIN_CONTROL"; + case CUBEB_FX_NOISE_SUPPRESSOR: + return "CUBEB_FX_NOISE_SUPPRESSOR"; + case CUBEB_FX_SENTINEL__: + return "UNKNOWN CUBEB_FX TYPE"; + } + return "UNKNOWN CUBEB_FX TYPE"; +} + extern "C" bool cubeb_fx_is_available(cubeb_jni * cubeb_jni_ptr, cubeb_fx_type type) { diff --git a/src/cubeb-jni.h b/src/cubeb-jni.h index 0a2d41a..8bbe3c8 100644 --- a/src/cubeb-jni.h +++ b/src/cubeb-jni.h @@ -17,6 +17,8 @@ extern "C" { cubeb_jni * cubeb_jni_init(); +const char * +cubeb_fx_type_description(cubeb_fx_type type); bool cubeb_fx_is_available(cubeb_jni * cubeb_jni_ptr, cubeb_fx_type type); cubeb_fx * diff --git a/src/cubeb_aaudio.cpp b/src/cubeb_aaudio.cpp index a8f596f..f7c9d23 100644 --- a/src/cubeb_aaudio.cpp +++ b/src/cubeb_aaudio.cpp @@ -65,9 +65,11 @@ using namespace std; X(AAudioStream_getState) \ X(AAudioStream_getFramesWritten) \ X(AAudioStream_getFramesPerBurst) \ + X(AAudioStream_getSessionId) \ X(AAudioStreamBuilder_setInputPreset) \ X(AAudioStreamBuilder_setUsage) \ - X(AAudioStreamBuilder_setFramesPerDataCallback) + X(AAudioStreamBuilder_setFramesPerDataCallback) \ + X(AAudioStreamBuilder_setSessionId) // not needed or added later on // X(AAudioStreamBuilder_setDeviceId) \ @@ -80,11 +82,9 @@ using namespace std; // X(AAudioStream_getXRunCount) \ // X(AAudioStream_isMMapUsed) \ // X(AAudioStreamBuilder_setContentType) \ - // X(AAudioStreamBuilder_setSessionId) \ // X(AAudioStream_getUsage) \ // X(AAudioStream_getContentType) \ // X(AAudioStream_getInputPreset) \ - // X(AAudioStream_getSessionId) \ // END: not needed or added later on #define MAKE_TYPEDEF(x) static decltype(x) * cubeb_##x; @@ -114,6 +114,10 @@ aaudio_stream_start_locked(cubeb_stream * stm, lock_guard<mutex> & lock); static void reinitialize_stream(cubeb_stream * stm); +static int +aaudio_get_supported_input_processing_params( + cubeb * ctx, cubeb_input_processing_params * params); + enum class stream_state { INIT = 0, STOPPED, @@ -136,6 +140,10 @@ struct AAudioTimingInfo { uint32_t input_latency; }; +struct cubeb_fx_delete { + void operator()(cubeb_fx * fx) { cubeb_fx_destroy(fx); } +}; + struct cubeb_stream { /* Note: Must match cubeb_stream layout in cubeb.c. */ cubeb * context{}; @@ -165,6 +173,7 @@ struct cubeb_stream { unique_ptr<cubeb_stream_params> output_stream_params; unique_ptr<cubeb_stream_params> input_stream_params; + unique_ptr<cubeb_fx, cubeb_fx_delete> fxs[CUBEB_FX_SENTINEL__]{}; uint32_t latency_frames{}; cubeb_sample_format out_format{}; uint32_t sample_rate{}; @@ -1192,13 +1201,12 @@ aaudio_stream_init_impl(cubeb_stream * stm, lock_guard<mutex> & lock) // input cubeb_stream_params in_params; if (stm->input_stream_params) { - // Match what the OpenSL backend does for now, we could use UNPROCESSED and - // VOICE_COMMUNICATION here, but we'd need to make it clear that - // application-level AEC and other voice processing should be disabled - // there. int input_preset = stm->voice_input ? AAUDIO_INPUT_PRESET_VOICE_RECOGNITION : AAUDIO_INPUT_PRESET_CAMCORDER; WRAP(AAudioStreamBuilder_setInputPreset)(sb, input_preset); + aaudio_session_id_t session_id = + stm->voice_input ? AAUDIO_SESSION_ID_ALLOCATE : AAUDIO_SESSION_ID_NONE; + WRAP(AAudioStreamBuilder_setSessionId)(sb, session_id); WRAP(AAudioStreamBuilder_setDirection)(sb, AAUDIO_DIRECTION_INPUT); WRAP(AAudioStreamBuilder_setDataCallback)(sb, in_data_callback, stm); assert(stm->latency_frames < std::numeric_limits<int32_t>::max()); @@ -1211,6 +1219,15 @@ aaudio_stream_init_impl(cubeb_stream * stm, lock_guard<mutex> & lock) return res_err; } + if (stm->voice_input) { + aaudio_session_id_t session = + WRAP(AAudioStream_getSessionId)(stm->istream); + for (size_t i = 0; i < CUBEB_FX_SENTINEL__; ++i) { + stm->fxs[i].reset(cubeb_fx_init( + stm->context->jni.get(), static_cast<cubeb_fx_type>(i), session)); + } + } + int32_t input_burst_size = WRAP(AAudioStream_getFramesPerBurst)(stm->istream); LOG("AAudio input burst size: %d", input_burst_size); @@ -1670,6 +1687,81 @@ aaudio_stream_set_volume(cubeb_stream * stm, float volume) return CUBEB_OK; } +static cubeb_input_processing_params +cubeb_fx_type_to_processing_param(cubeb_fx_type type) +{ + switch (type) { + case CUBEB_FX_ACOUSTIC_ECHO_CANCELER: + return CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION; + case CUBEB_FX_AUTOMATIC_GAIN_CONTROL: + return CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL; + case CUBEB_FX_NOISE_SUPPRESSOR: + return CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION; + case CUBEB_FX_SENTINEL__: + return CUBEB_INPUT_PROCESSING_PARAM_NONE; + } + return CUBEB_INPUT_PROCESSING_PARAM_NONE; +} + +static int +aaudio_set_input_processing_params(cubeb_stream * stm, + cubeb_input_processing_params params) +{ + assert(stm); + + if (!stm->istream) { + LOG("%s: no input stream", __func__); + return CUBEB_ERROR_INVALID_PARAMETER; + } + + if (!stm->voice_input) { + LOG("%s: input stream is not a voice stream", __func__); + return CUBEB_ERROR_INVALID_PARAMETER; + } + + // Make sure we support all the effects we are trying to enable. + cubeb_input_processing_params supported = CUBEB_INPUT_PROCESSING_PARAM_NONE; + aaudio_get_supported_input_processing_params(stm->context, &supported); + cubeb_input_processing_params intersection = + static_cast<cubeb_input_processing_params>(supported & params); + if (intersection != params) { + LOG("%s: attempted to set an unsupported param. supported=%d, params=%d", + __func__, supported, params); + return CUBEB_ERROR_INVALID_PARAMETER; + } + + // Make sure we have instances of all the effects we are trying to enable. + bool fx_params[CUBEB_FX_SENTINEL__]{}; + for (size_t i = 0; i < CUBEB_FX_SENTINEL__; ++i) { + const cubeb_fx_type fx_type = static_cast<cubeb_fx_type>(i); + const cubeb_input_processing_params param = + cubeb_fx_type_to_processing_param(fx_type); + fx_params[i] = params & param; + + if (!stm->fxs[i] && fx_params[i]) { + LOG("%s: attempted to enable %s that we don't have", __func__, + cubeb_fx_type_description(fx_type)); + return CUBEB_ERROR; + } + } + + // Set enabled state of all the effect instances we have. + for (size_t i = 0; i < CUBEB_FX_SENTINEL__; ++i) { + const cubeb_fx_type fx_type = static_cast<cubeb_fx_type>(i); + if (cubeb_fx * fx = stm->fxs[i].get()) { + if (int e = cubeb_fx_set_enabled(fx, fx_params[i])) { + LOG("%s: failed to %s %s. e=%d", __func__, + fx_params[i] ? "enable" : "disable", + cubeb_fx_type_description(fx_type), e); + return CUBEB_ERROR; + } + } + } + + LOG("%s: successfully set params %d", __func__, params); + return CUBEB_OK; +} + aaudio_data_callback_result_t dummy_callback(AAudioStream * stream, void * userData, void * audioData, int32_t numFrames) @@ -1798,7 +1890,7 @@ const static struct cubeb_ops aaudio_ops = { /*.stream_set_name =*/nullptr, /*.stream_get_current_device =*/nullptr, /*.stream_set_input_mute =*/nullptr, - /*.stream_set_input_processing_params =*/nullptr, + /*.stream_set_input_processing_params =*/aaudio_set_input_processing_params, /*.stream_device_destroy =*/nullptr, /*.stream_register_device_changed_callback =*/nullptr, /*.register_device_collection_changed =*/nullptr}; |