aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cubeb-jni.cpp16
-rw-r--r--src/cubeb-jni.h2
-rw-r--r--src/cubeb_aaudio.cpp108
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};