diff --git a/base/cvd/cuttlefish/host/frontend/webrtc/BUILD.bazel b/base/cvd/cuttlefish/host/frontend/webrtc/BUILD.bazel index ab1d9ec05cd..344187a0e5d 100644 --- a/base/cvd/cuttlefish/host/frontend/webrtc/BUILD.bazel +++ b/base/cvd/cuttlefish/host/frontend/webrtc/BUILD.bazel @@ -88,6 +88,15 @@ cf_cc_library( ], ) +cf_cc_library( + name = "libcuttlefish_webrtc_audio_channel_matrix", + srcs = ["audio_channel_matrix.cpp"], + hdrs = ["audio_channel_matrix.h"], + deps = [ + "@abseil-cpp//absl/log:check", + ], +) + cf_cc_library( name = "libcuttlefish_webrtc_audio_mixer", srcs = ["audio_mixer.cpp"], @@ -96,6 +105,7 @@ cf_cc_library( depend_on_what_you_use_enabled = False, include_cleaner_enabled = False, deps = [ + ":libcuttlefish_webrtc_audio_channel_matrix", ":libcuttlefish_webrtc_audio_settings", "//cuttlefish/host/frontend/webrtc/libdevice:audio_sink", "//libbase", diff --git a/base/cvd/cuttlefish/host/frontend/webrtc/audio_channel_matrix.cpp b/base/cvd/cuttlefish/host/frontend/webrtc/audio_channel_matrix.cpp new file mode 100644 index 00000000000..6eb95b4675c --- /dev/null +++ b/base/cvd/cuttlefish/host/frontend/webrtc/audio_channel_matrix.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2026 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cuttlefish/host/frontend/webrtc/audio_channel_matrix.h" + +#include +#include +#include +#include + +#include "absl/log/check.h" + +namespace cuttlefish { + +std::vector> BuildChannelMixingMatrix(uint8_t dst_channels, + uint8_t src_channels, + float volume) { + CHECK(volume >= 0) << "volume can't be negative"; + + std::vector> matrix( + dst_channels, std::vector(src_channels, 0.0f)); + + // As of now we only use direct channel mapping + const size_t mapped_channels = std::min(dst_channels, src_channels); + for (size_t i = 0; i < mapped_channels; ++i) { + matrix[i][i] = volume; + } + + return matrix; +} + +} // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/frontend/webrtc/audio_channel_matrix.h b/base/cvd/cuttlefish/host/frontend/webrtc/audio_channel_matrix.h new file mode 100644 index 00000000000..75daa968fe1 --- /dev/null +++ b/base/cvd/cuttlefish/host/frontend/webrtc/audio_channel_matrix.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2026 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace cuttlefish { + +/** + * Builds the matrix used to mix a stream's source channels into a sink's + * destination channels. + * + * Each source channel is mapped to the destination channel of the same index + * and scaled by `volume`. Channels present on only one side are dropped. + * + * @param dst_channels Destination sink channels (e.g. 2 for a stereo sink) + * @param src_channels Source stream channels (e.g. 6 for 5.1 surround) + * @param volume Master stream volume [0.0 - 1.0] + * @return Mixing coefficients, indexed [destination channel][source channel] + */ +std::vector> BuildChannelMixingMatrix(uint8_t dst_channels, + uint8_t src_channels, + float volume); + +} // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.cpp b/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.cpp index 882beb91628..50a3fb8cfb6 100644 --- a/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.cpp +++ b/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.cpp @@ -7,6 +7,8 @@ #include "absl/log/check.h" +#include "cuttlefish/host/frontend/webrtc/audio_channel_matrix.h" + namespace cuttlefish { namespace { @@ -170,12 +172,11 @@ void AudioMixer::OnPlayback(uint32_t stream_id, uint32_t stream_sample_rate, const auto frames_count = GetFrameCountAfterResampling( sample_rate_, stream_sample_rate, stream_frames_count); - std::unique_lock lock(mutex_); - // As of now we only use direct channel mapping - for(size_t i = 0; i < channles_map.size(); ++i) { - channles_map[i][i] = volume; - } + const std::vector> channels_map = + BuildChannelMixingMatrix(channels_count_, stream_channels_count, volume); + + std::unique_lock lock(mutex_); const bool need_notify = next_frame_.empty(); // no active streams @@ -204,7 +205,7 @@ void AudioMixer::OnPlayback(uint32_t stream_id, uint32_t stream_sample_rate, const auto filled_frames_count = convert_fn(mixed_buffer_.data() + next_frame_id * frame_size_bytes_, channels_count_, sample_rate_, buffer, stream_channels_count, - stream_sample_rate, stream_frames_count, channles_map); + stream_sample_rate, stream_frames_count, channels_map); CHECK(filled_frames_count <= frames_count); next_frame_[stream_id] = next_frame_id + filled_frames_count; diff --git a/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.h b/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.h index 4ecd8e3d2a2..d084d1b4763 100644 --- a/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.h +++ b/base/cvd/cuttlefish/host/frontend/webrtc/audio_mixer.h @@ -58,16 +58,6 @@ class AudioMixer { // Frame index per stream to put next available data to std::unordered_map next_frame_; - // Used to remap channels and apply volume levels - std::vector> channles_map = {{ - {1, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0}, - {0, 0, 1, 0, 0, 0}, - {0, 0, 0, 1, 0, 0}, - {0, 0, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 1}, - }}; - //////////////////////////////////////////////////// ////////////////////////////////////////////////////