Skip to content

Commit

Permalink
audio_handler: Change volume by number_of_volume_steps
Browse files Browse the repository at this point in the history
Add new data member number_of_volume_steps to audio_device,
and get this data from audio_node.
Also fix relevant unittest for this change.

In IncreaseOutputVolumeByOneStep,
set a new volume one step higher than the current volume.
In DecreaseOutputVolumeByOneStep,
set a new volume one step lower than the current volume.

Previously, we simply changed 4% each time,
but this could cause the user to feel no volume change after the volume up/down event.
Doing this allows the user to feel volume change every event.

BUG=b:215297837
TEST=autoninja -C out/Default/ ash_components_unittests

Change-Id: I6670903267c267b148133f524f9df7e039f98f63
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3801854
Commit-Queue: Ching Yun Chang <whalechang@google.com>
Reviewed-by: Hsinyu Chao <hychao@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1039164}
  • Loading branch information
whalechang authored and Chromium LUCI CQ committed Aug 25, 2022
1 parent 9d943bd commit 8c2ca90
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
1 change: 1 addition & 0 deletions chromeos/ash/components/audio/audio_device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ AudioDevice::AudioDevice(const AudioNode& node) {
plugged_time = node.plugged_time;
max_supported_channels = node.max_supported_channels;
audio_effect = node.audio_effect;
number_of_volume_steps = node.number_of_volume_steps;
}

AudioDevice::AudioDevice(const AudioDevice& other) = default;
Expand Down
1 change: 1 addition & 0 deletions chromeos/ash/components/audio/audio_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ struct COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_AUDIO) AudioDevice {
uint64_t plugged_time = 0;
uint32_t max_supported_channels = 0;
uint32_t audio_effect = 0;
int32_t number_of_volume_steps = 0;
};

typedef std::vector<AudioDevice> AudioDeviceList;
Expand Down
38 changes: 38 additions & 0 deletions chromeos/ash/components/audio/cras_audio_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,44 @@ void CrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) {
SetOutputVolumePercent(output_volume_ + adjust_by_percent);
}

void CrasAudioHandler::IncreaseOutputVolumeByOneStep() {
// Set all active devices to the same volume.
for (const auto& item : audio_devices_) {
const AudioDevice& device = item.second;
if (!device.is_input && device.active) {
int32_t volume_level =
std::round((double)output_volume_ *
(double)device.number_of_volume_steps * 0.01);
if (volume_level == 0 && output_volume_ > 0) {
volume_level = 1;
}
// increase one level and convert to volume
output_volume_ = std::min(
100,
static_cast<int>(std::floor(((double)(volume_level + 1)) /
device.number_of_volume_steps * 100)));
SetOutputNodeVolumePercent(device.id, output_volume_);
}
}
}

void CrasAudioHandler::DecreaseOutputVolumeByOneStep() {
// Set all active devices to the same volume.
for (const auto& item : audio_devices_) {
const AudioDevice& device = item.second;
if (!device.is_input && device.active) {
int32_t volume_level =
std::round((double)output_volume_ *
(double)device.number_of_volume_steps * 0.01);
// decrease one level and convert to volume
output_volume_ = std::max(
0, static_cast<int>(std::floor(((double)(volume_level - 1)) /
device.number_of_volume_steps * 100)));
SetOutputNodeVolumePercent(device.id, output_volume_);
}
}
}

void CrasAudioHandler::SetOutputMute(bool mute_on) {
if (!SetOutputMuteInternal(mute_on))
return;
Expand Down
6 changes: 6 additions & 0 deletions chromeos/ash/components/audio/cras_audio_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_AUDIO) CrasAudioHandler
// (negative percentage).
void AdjustOutputVolumeByPercent(int adjust_by_percent);

// Adjusts all active output devices' volume higher by one volume step.
void IncreaseOutputVolumeByOneStep();

// Adjusts all active output devices' volume lower by one volume step
void DecreaseOutputVolumeByOneStep();

// Adjusts all active output devices' volume to a minimum audible level if it
// is too low.
void AdjustOutputVolumeToAudibleLevel();
Expand Down
121 changes: 121 additions & 0 deletions chromeos/ash/components/audio/cras_audio_handler_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2121,6 +2121,127 @@ TEST_P(CrasAudioHandlerTest, SetOutputVolumePercent) {
EXPECT_EQ(kVolume, audio_pref_handler_->GetOutputVolumeValue(&device));
}

TEST_P(CrasAudioHandlerTest, IncreaseOutputVolumeByOneStep) {
AudioNodeList audio_nodes =
GenerateAudioNodeList({kUSBHeadphone1, kUSBHeadphone2});
SetUpCrasAudioHandler(audio_nodes);
// USB 1 have 25 steps, mean we increase 100/25=4 % of volume per step.
// USB 1 start from volume 0 and increase one step expect increase to 4.
cras_audio_handler_->ChangeActiveNodes({kUSBHeadphone1->id});
cras_audio_handler_->SetOutputVolumePercent(0);
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
EXPECT_EQ(4, cras_audio_handler_->GetOutputVolumePercent());
// 0 -> step0
// 1-4 -> step1
// 5-8 -> step2
// Inorder to let user feel volume change, increase step1 to step2.
// USB 1 start from volume 2 and increase one step, expect increase to 8.
cras_audio_handler_->SetOutputVolumePercent(2);
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
EXPECT_EQ(8, cras_audio_handler_->GetOutputVolumePercent());
// 100 is max volume
cras_audio_handler_->SetOutputVolumePercent(100);
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
EXPECT_EQ(100, cras_audio_handler_->GetOutputVolumePercent());
// can increase from 0 to 100
cras_audio_handler_->SetOutputVolumePercent(0);
for (int32_t i = 0; i < kUSBHeadphone1->number_of_volume_steps; ++i) {
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
}
EXPECT_EQ(100, cras_audio_handler_->GetOutputVolumePercent());
// USB 2 have 16 steps, mean we increase 100/16=6.25 % of volume per step.
// USB 2 start from volume 0 and increase one step expect increase to 6;
cras_audio_handler_->ChangeActiveNodes({kUSBHeadphone2->id});
cras_audio_handler_->SetOutputVolumePercent(0);
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
EXPECT_EQ(6, cras_audio_handler_->GetOutputVolumePercent());
// 0 -> step0
// 1-6 -> step1
// 7-12 -> step2
// Inorder to let user feel volume change, increase step1 to step2.
// USB 2 start from volume 4 and increase one step, expect increase to 12
cras_audio_handler_->SetOutputVolumePercent(4);
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
EXPECT_EQ(12, cras_audio_handler_->GetOutputVolumePercent());
// USB 2 start from volume 0 and increase 4 step, expect increase to
// 25(6.25*4=25)
cras_audio_handler_->SetOutputVolumePercent(0);
for (int32_t i = 0; i < 4; ++i) {
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
}
EXPECT_EQ(25, cras_audio_handler_->GetOutputVolumePercent());
// 100 is max
cras_audio_handler_->SetOutputVolumePercent(100);
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
EXPECT_EQ(100, cras_audio_handler_->GetOutputVolumePercent());
// can increase from 0 to 100
cras_audio_handler_->SetOutputVolumePercent(0);
for (uint32_t i = 0; i < kUSBHeadphone2->number_of_volume_steps; ++i) {
cras_audio_handler_->IncreaseOutputVolumeByOneStep();
}
EXPECT_EQ(100, cras_audio_handler_->GetOutputVolumePercent());
}

TEST_P(CrasAudioHandlerTest, DecreaseOutputVolumeByOneStep) {
AudioNodeList audio_nodes =
GenerateAudioNodeList({kUSBHeadphone1, kUSBHeadphone2});
SetUpCrasAudioHandler(audio_nodes);
// USB 1 have 25 steps, mean we decrease 100/25=4 % of volume per step.
// USB 1 start from volume 4 and decrease one step expect decrease to 0;
cras_audio_handler_->ChangeActiveNodes({kUSBHeadphone1->id});
cras_audio_handler_->SetOutputVolumePercent(4);
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
EXPECT_EQ(0, cras_audio_handler_->GetOutputVolumePercent());
// 0 -> step0
// 1-4 -> step1
// 4-8 -> step2
// Inorder to let user feel volume change, decrease step2 to step1.
// USB 1 start from volume 6 and decrease one step, expect decrease to 4
cras_audio_handler_->SetOutputVolumePercent(6);
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
EXPECT_EQ(4, cras_audio_handler_->GetOutputVolumePercent());
// 0 is min volume
cras_audio_handler_->SetOutputVolumePercent(0);
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
EXPECT_EQ(0, cras_audio_handler_->GetOutputVolumePercent());
// can decrease from 100 to 0
cras_audio_handler_->SetOutputVolumePercent(100);
for (int32_t i = 0; i < kUSBHeadphone1->number_of_volume_steps; ++i) {
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
}
EXPECT_EQ(0, cras_audio_handler_->GetOutputVolumePercent());
// USB 2 have 16 steps, mean we decrease 100/16=6.25 % of volume per step.
// USB 2 start from volume 12 and decrease one step expect decrease to 6;
cras_audio_handler_->ChangeActiveNodes({kUSBHeadphone2->id});
cras_audio_handler_->SetOutputVolumePercent(12);
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
EXPECT_EQ(6, cras_audio_handler_->GetOutputVolumePercent());
// 0 -> step0
// 1-6 -> step1
// 7-12 -> step2
// Inorder to let user feel volume change, decrease step2 to step1.
// USB 2 start from volume 10 and decrease one step, expect decrease to 6
cras_audio_handler_->SetOutputVolumePercent(10);
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
EXPECT_EQ(6, cras_audio_handler_->GetOutputVolumePercent());
// USB 2 start from volume 25 and decrease 4 step, expect decrease to 0
cras_audio_handler_->SetOutputVolumePercent(25);
for (int32_t i = 0; i < 4; ++i) {
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
}
EXPECT_EQ(0, cras_audio_handler_->GetOutputVolumePercent());
// 0 is min volume
cras_audio_handler_->SetOutputVolumePercent(0);
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
EXPECT_EQ(0, cras_audio_handler_->GetOutputVolumePercent());
// can decrease from 100 to 0
cras_audio_handler_->SetOutputVolumePercent(100);
for (int32_t i = 0; i < kUSBHeadphone2->number_of_volume_steps; ++i) {
cras_audio_handler_->DecreaseOutputVolumeByOneStep();
}
EXPECT_EQ(0, cras_audio_handler_->GetOutputVolumePercent());
}

TEST_P(CrasAudioHandlerTest, RestartAudioClientWithCrasReady) {
AudioNodeList audio_nodes = GenerateAudioNodeList({kInternalSpeaker});
SetUpCrasAudioHandler(audio_nodes);
Expand Down

0 comments on commit 8c2ca90

Please sign in to comment.