Skip to content

Commit

Permalink
CRAS: add UCM controls for spatial audio.
Browse files Browse the repository at this point in the history
Add UCM controls to enable/disable spatial audio.
Configure spatial audio when opening devices to enable the switch
of spatial audio ability.

BUG=b:317748801
TEST=FEATURES=test USE=asan emerge-${BOARD} adhd, bazel test //...

Change-Id: I128b6e5af413e7116a92abd414de7e5bed0a7c4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/5854773
Commit-Queue: Eddy Hsu <eddyhsu@chromium.org>
Reviewed-by: Li-Yu Yu <aaronyu@google.com>
Tested-by: Li-Yu Yu <aaronyu@google.com>
  • Loading branch information
Eddy Hsu authored and Chromeos LUCI committed Oct 4, 2024
1 parent cd52040 commit cf12420
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 0 deletions.
20 changes: 20 additions & 0 deletions cras/src/server/cras_alsa_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "cras/common/check.h"
#include "cras/server/cras_trace.h"
#include "cras/server/s2/s2.h"
#include "cras/src/common/cras_alsa_card_info.h"
#include "cras/src/common/cras_log.h"
#include "cras/src/common/cras_string.h"
Expand Down Expand Up @@ -85,6 +86,8 @@ struct alsa_io {
bool dsp_noise_suppression_enabled;
// If gain control is enabled in DSP
bool dsp_gain_control_enabled;
// If spatial audio is enabled in DSP
bool dsp_spatial_audio_enabled;
// Use case of this device according to UCM.
enum CRAS_USE_CASE use_case;
// Pointer to the shared group info. NULL if the device is not in a group.
Expand Down Expand Up @@ -2128,6 +2131,18 @@ static void cras_iodev_update_speaker_rotation(struct cras_iodev* iodev) {
cras_iodev_update_dsp(iodev);
}

static void cras_iodev_update_spatial_audio(struct cras_iodev* iodev) {
struct alsa_io* aio = (struct alsa_io*)iodev;
struct cras_use_case_mgr* ucm = aio->common.ucm;

if (iodev->active_node && ucm_node_spatial_audio_exists(ucm)) {
bool enable_dsp_spatial_audio = cras_s2_get_spatial_audio_enabled();

ucm_enable_node_spatial_audio(ucm, enable_dsp_spatial_audio);
aio->dsp_spatial_audio_enabled = enable_dsp_spatial_audio;
}
}

/*
* Exported Interface.
*/
Expand Down Expand Up @@ -2297,6 +2312,11 @@ struct cras_iodev* alsa_iodev_create(
iodev->software_volume_needed = 1;
}

// Only internal speaker supports spatial audio.
if (direction == CRAS_STREAM_OUTPUT && strstr(dev_name, INTERNAL_SPEAKER)) {
iodev->spatial_audio_changed = cras_iodev_update_spatial_audio;
}

/* Add this now so that cleanup of the iodev (in case of error or card
* card removal will function as expected. */
cras_iodev_list_add(&aio->common.base);
Expand Down
10 changes: 10 additions & 0 deletions cras/src/server/cras_alsa_ucm.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static const char rtc_proc_echo_cancellation_modifier[] =
static const char rtc_proc_noise_suppression_modifier[] =
"RTC Proc Noise Suppression";
static const char rtc_proc_gain_control_modifier[] = "RTC Proc Gain Control";
static const char spatial_audio_modifier[] = "Internal Speaker Spatial Audio";

// SectionModifier prefixes and suffixes.
static const char hotword_model_prefix[] = "Hotword Model";
Expand Down Expand Up @@ -631,6 +632,15 @@ int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr* mgr,
return ucm_modifier_try_enable(mgr, enable, node_modifier_name);
}

int inline ucm_node_spatial_audio_exists(struct cras_use_case_mgr* mgr) {
return ucm_mod_exists_with_name(mgr, spatial_audio_modifier);
}

int inline ucm_enable_node_spatial_audio(struct cras_use_case_mgr* mgr,
int enable) {
return ucm_modifier_try_enable(mgr, enable, spatial_audio_modifier);
}

int ucm_set_enabled(struct cras_use_case_mgr* mgr,
const char* dev,
int enable) {
Expand Down
20 changes: 20 additions & 0 deletions cras/src/server/cras_alsa_ucm.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,26 @@ int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr* mgr,
const char* node_name,
int enable);

/* Checks if modifier of spatial audio in ucm.
* Args:
* mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create.
* node_name - The node name.
* Returns:
* 1 if it exists, 0 otherwise.
*/
int ucm_node_spatial_audio_exists(struct cras_use_case_mgr* mgr);

/* Enables or disables spatial audio. First checks if the modifier is
* already enabled or disabled.
* Args:
* mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create.
* node_name - The node name.
* enable - Enable device if non-zero.
* Returns:
* 0 on success or negative error code on failure.
*/
int ucm_enable_node_spatial_audio(struct cras_use_case_mgr* mgr, int enable);

/* Enables or disables a UCM device. First checks if the device is already
* enabled or disabled.
* Args:
Expand Down
1 change: 1 addition & 0 deletions cras/src/server/cras_dbus_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1531,6 +1531,7 @@ static DBusHandlerResult handle_set_spatial_audio_enabled(DBusConnection* conn,
}

cras_s2_set_spatial_audio_enabled(enabled);
cras_iodev_list_update_for_spatial_audio();

return send_empty_reply(conn, message);
}
Expand Down
3 changes: 3 additions & 0 deletions cras/src/server/cras_iodev.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,9 @@ struct cras_iodev {
// time with MONOTONIC_RAW clock as the timestamp.
int (*get_htimestamp)(const struct cras_iodev* iodev, struct timespec* ts);

// Callback when spatial audio is changed in system state
void (*spatial_audio_changed)(struct cras_iodev* iodev);

// The audio format being rendered or captured to hardware.
struct cras_audio_format* format;
// Rate estimator to estimate the actual device rate.
Expand Down
13 changes: 13 additions & 0 deletions cras/src/server/cras_iodev_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -2929,3 +2929,16 @@ bool cras_iodev_list_is_floop_dev(int dev_idx) {
return dev && dev->active_node &&
dev->active_node->type == CRAS_NODE_TYPE_FLOOP;
}

static inline void update_spatial_audio_inner(struct cras_iodev* iodev) {
if (iodev->spatial_audio_changed) {
iodev->spatial_audio_changed(iodev);
}
}

void cras_iodev_list_update_for_spatial_audio() {
struct cras_iodev* iodev;

FOR_ALL_DEVS(devs, CRAS_STREAM_OUTPUT, iodev,
update_spatial_audio_inner(iodev));
}
4 changes: 4 additions & 0 deletions cras/src/server/cras_iodev_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ bool cras_iodev_list_is_utility_stream(const struct cras_rstream* stream);
/* Returns true if a given dev_idx is a floop device */
bool cras_iodev_list_is_floop_dev(int dev_idx);

/* Sets the state of spatial audio for output devices.
*/
void cras_iodev_list_update_for_spatial_audio();

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
1 change: 1 addition & 0 deletions cras/src/tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ cc_test(
"//cras/common:check",
"//cras/server:cras_trace",
"//cras/server/platform/dlc:cc",
"//cras/server/s2:cc",
"//cras/src/common:all_headers",
"//cras/src/common:cras_log",
"//cras/src/server:all_headers",
Expand Down
12 changes: 12 additions & 0 deletions cras/src/tests/alsa_io_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2772,6 +2772,10 @@ int cras_system_get_using_default_volume_curve_for_usb_audio_device() {
return sys_using_default_volume_curve_for_usb_audio_device_value;
}

bool cras_system_get_spatial_audio_enabled() {
return false;
}

// From cras_alsa_mixer.
void cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer* m,
long dB_level,
Expand Down Expand Up @@ -3050,6 +3054,14 @@ int ucm_node_echo_cancellation_exists(struct cras_use_case_mgr* mgr) {
return ucm_node_echo_cancellation_exists_ret_value;
}

int ucm_node_spatial_audio_exists(struct cras_use_case_mgr* mgr) {
return 0;
}

int ucm_enable_node_spatial_audio(struct cras_use_case_mgr* mgr, int enable) {
return 0;
}

struct cras_volume_curve* cras_volume_curve_create_simple_step(long max_volume,
long range) {
cras_volume_curve_create_simple_step_called++;
Expand Down
12 changes: 12 additions & 0 deletions cras/src/tests/cras_alsa_usb_io_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,10 @@ int cras_system_aec_on_dsp_supported() {
return sys_aec_on_dsp_supported_return_value;
}

bool cras_system_get_spatial_audio_enabled() {
return false;
}

// From cras_alsa_mixer.
void cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer* m,
long dB_level,
Expand Down Expand Up @@ -1487,6 +1491,14 @@ int ucm_node_echo_cancellation_exists(struct cras_use_case_mgr* mgr) {
return ucm_node_echo_cancellation_exists_ret_value;
}

int ucm_node_spatial_audio_exists(struct cras_use_case_mgr* mgr) {
return 0;
}

int ucm_enable_node_spatial_audio(struct cras_use_case_mgr* mgr, int enable) {
return 0;
}

struct cras_volume_curve* cras_volume_curve_create_simple_step(long max_volume,
long range) {
cras_volume_curve_create_simple_step_called++;
Expand Down
3 changes: 3 additions & 0 deletions cras/src/tests/dbus_control_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,7 @@ void cras_observer_remove(struct cras_observer_client* client) {
void cras_system_set_force_respect_ui_gains_enabled(bool enabled) {
return;
}
void cras_iodev_list_update_for_spatial_audio() {
return;
}
} // extern "C"

0 comments on commit cf12420

Please sign in to comment.