[CodeHealth] Remove AudioBus::channel() usage (part 1)
This CL removes some uses of AudioBus::channel(), in favor of the safer AudioBus::channel_span(). Bug: 373960632 Change-Id: Icbec30d12c65117369e215774271281f2ada7294 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6116936 Auto-Submit: Thomas Guilbert <tguilbert@chromium.org> Reviewed-by: Dale Curtis <dalecurtis@chromium.org> Commit-Queue: Dale Curtis <dalecurtis@chromium.org> Cr-Commit-Position: refs/heads/main@{#1401866}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
40ce1454d1
commit
9583255961
@ -349,11 +349,9 @@ void AudioBus::CopyAndClipTo(AudioBus* dest) const {
|
||||
DCHECK(!is_bitstream_format_);
|
||||
CHECK_EQ(channels(), dest->channels());
|
||||
CHECK_LE(frames(), dest->frames());
|
||||
for (int i = 0; i < channels(); ++i) {
|
||||
float* dest_ptr = dest->channel(i);
|
||||
const float* source_ptr = channel(i);
|
||||
for (int j = 0; j < frames(); ++j)
|
||||
dest_ptr[j] = Float32SampleTypeTraits::FromFloat(source_ptr[j]);
|
||||
for (int ch = 0; ch < channels(); ++ch) {
|
||||
std::ranges::transform(channel_span(ch), dest->channel_span(ch).begin(),
|
||||
Float32SampleTypeTraits::FromFloat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,23 +361,25 @@ void AudioBus::CopyPartialFramesTo(int source_start_frame,
|
||||
AudioBus* dest) const {
|
||||
DCHECK(!is_bitstream_format_);
|
||||
CHECK_EQ(channels(), dest->channels());
|
||||
CHECK_LE(source_start_frame + frame_count, frames());
|
||||
CHECK_LE(dest_start_frame + frame_count, dest->frames());
|
||||
|
||||
const size_t source_offset = base::checked_cast<size_t>(source_start_frame);
|
||||
const size_t dest_offset = base::checked_cast<size_t>(dest_start_frame);
|
||||
const size_t count = base::checked_cast<size_t>(frame_count);
|
||||
|
||||
// Since we don't know if the other AudioBus is wrapped or not (and we don't
|
||||
// want to care), just copy using the public channel() accessors.
|
||||
for (int i = 0; i < channels(); ++i) {
|
||||
memcpy(dest->channel(i) + dest_start_frame,
|
||||
channel(i) + source_start_frame,
|
||||
sizeof(*channel(i)) * frame_count);
|
||||
ConstChannel src_span = channel_span(i).subspan(source_offset, count);
|
||||
dest->channel_span(i).subspan(dest_offset, count).copy_from(src_span);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioBus::Scale(float volume) {
|
||||
DCHECK(!is_bitstream_format_);
|
||||
if (volume > 0 && volume != 1) {
|
||||
for (int i = 0; i < channels(); ++i)
|
||||
vector_math::FMUL(channel(i), volume, frames(), channel(i));
|
||||
for (auto channel : channel_data_) {
|
||||
vector_math::FMUL(channel.data(), volume, frames(), channel.data());
|
||||
}
|
||||
} else if (volume == 0) {
|
||||
Zero();
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ void AudioBus::CopyConvertFromInterleavedSourceToAudioBus(
|
||||
AudioBus* dest) {
|
||||
const int channels = dest->channels();
|
||||
for (int ch = 0; ch < channels; ++ch) {
|
||||
float* channel_data = dest->channel(ch);
|
||||
AudioBus::Channel channel_data = dest->channel_span(ch);
|
||||
for (int target_frame_index = write_offset_in_frames,
|
||||
read_pos_in_source = ch;
|
||||
target_frame_index < write_offset_in_frames + num_frames_to_write;
|
||||
@ -377,7 +377,7 @@ void AudioBus::CopyConvertFromAudioBusToInterleavedTarget(
|
||||
typename TargetSampleTypeTraits::ValueType* dest_buffer) {
|
||||
const int channels = source->channels();
|
||||
for (int ch = 0; ch < channels; ++ch) {
|
||||
const float* channel_data = source->channel(ch);
|
||||
AudioBus::ConstChannel channel_data = source->channel_span(ch);
|
||||
for (int source_frame_index = read_offset_in_frames, write_pos_in_dest = ch;
|
||||
source_frame_index < read_offset_in_frames + num_frames_to_read;
|
||||
++source_frame_index, write_pos_in_dest += channels) {
|
||||
|
@ -29,10 +29,12 @@
|
||||
|
||||
namespace media {
|
||||
|
||||
using AlignedFloatArray = base::AlignedHeapArray<float>;
|
||||
|
||||
static const int kChannels = 6;
|
||||
static constexpr ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1;
|
||||
// Use a buffer size which is intentionally not a multiple of kChannelAlignment.
|
||||
static const int kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1;
|
||||
static const size_t kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1;
|
||||
static const int kSampleRate = 48000;
|
||||
|
||||
class AudioBusTest : public testing::Test {
|
||||
@ -42,19 +44,17 @@ class AudioBusTest : public testing::Test {
|
||||
AudioBusTest(const AudioBusTest&) = delete;
|
||||
AudioBusTest& operator=(const AudioBusTest&) = delete;
|
||||
|
||||
~AudioBusTest() override {
|
||||
for (size_t i = 0; i < data_.size(); ++i)
|
||||
base::AlignedFree(data_[i]);
|
||||
}
|
||||
~AudioBusTest() override = default;
|
||||
|
||||
void VerifyChannelAndFrameCount(AudioBus* bus) {
|
||||
EXPECT_EQ(kChannels, bus->channels());
|
||||
EXPECT_EQ(kFrameCount, bus->frames());
|
||||
EXPECT_EQ(static_cast<int>(kFrameCount), bus->frames());
|
||||
}
|
||||
|
||||
void VerifyArrayIsFilledWithValue(const float data[], int size, float value) {
|
||||
for (int i = 0; i < size; ++i)
|
||||
void VerifySpanIsFilledWithValue(AudioBus::ConstChannel data, float value) {
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify values for each channel in |result| are within |epsilon| of
|
||||
@ -77,10 +77,11 @@ class AudioBusTest : public testing::Test {
|
||||
SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i));
|
||||
|
||||
if (epsilon == 0) {
|
||||
ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]);
|
||||
ASSERT_FLOAT_EQ(expected->channel_span(ch)[i],
|
||||
result->channel_span(ch)[i]);
|
||||
} else {
|
||||
ASSERT_NEAR(expected->channel(ch)[i], result->channel(ch)[i],
|
||||
epsilon);
|
||||
ASSERT_NEAR(expected->channel_span(ch)[i],
|
||||
result->channel_span(ch)[i], epsilon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,22 +96,23 @@ class AudioBusTest : public testing::Test {
|
||||
// the Zero() method and verify it does as advertised. Also test data if data
|
||||
// is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h).
|
||||
void VerifyReadWriteAndAlignment(AudioBus* bus) {
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
int channel_count = 0;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
// Verify that the address returned by channel(i) is a multiple of
|
||||
// AudioBus::kChannelAlignment.
|
||||
ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(
|
||||
bus->channel(i)) & (AudioBus::kChannelAlignment - 1));
|
||||
|
||||
ASSERT_TRUE(AudioBus::IsAligned(channel));
|
||||
// Write into the channel buffer.
|
||||
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i);
|
||||
std::ranges::fill(channel, channel_count++);
|
||||
}
|
||||
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), i);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
VerifySpanIsFilledWithValue(bus->channel_span(i), i);
|
||||
}
|
||||
|
||||
bus->Zero();
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
VerifySpanIsFilledWithValue(bus->channel_span(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify copying to and from |bus1| and |bus2|.
|
||||
@ -142,12 +144,22 @@ class AudioBusTest : public testing::Test {
|
||||
void AllocateDataPerChannel() {
|
||||
data_.reserve(kChannels);
|
||||
for (int i = 0; i < kChannels; ++i) {
|
||||
data_.push_back(static_cast<float*>(base::AlignedAlloc(
|
||||
sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
|
||||
data_.push_back(
|
||||
base::AlignedUninit<float>(kFrameCount, AudioBus::kChannelAlignment));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float*> data_;
|
||||
// TODO(crbug.com/373960632): remove this when all ctors take spans.
|
||||
std::vector<float*> GetRawPointers(std::vector<AlignedFloatArray>& data) {
|
||||
std::vector<float*> result;
|
||||
result.reserve(data_.size());
|
||||
for (AlignedFloatArray& array : data) {
|
||||
result.push_back(array.as_span().data());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<AlignedFloatArray> data_;
|
||||
};
|
||||
|
||||
// Verify basic Create(...) method works as advertised.
|
||||
@ -174,8 +186,7 @@ TEST_F(AudioBusTest, CreateWrapper) {
|
||||
std::unique_ptr<AudioBus> bus = AudioBus::CreateWrapper(kChannels);
|
||||
bus->set_frames(kFrameCount);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
bus->SetChannelData(i,
|
||||
base::span(data_[i], static_cast<size_t>(kFrameCount)));
|
||||
bus->SetChannelData(i, data_[i].as_span());
|
||||
}
|
||||
|
||||
bool deleted = false;
|
||||
@ -197,8 +208,8 @@ TEST_F(AudioBusTest, AllChannels) {
|
||||
bus->set_frames(kFrameCount);
|
||||
AudioBus::ChannelVector channels;
|
||||
int value = 1;
|
||||
for (float* data : data_) {
|
||||
AudioBus::Channel channel(data, static_cast<size_t>(kFrameCount));
|
||||
for (AlignedFloatArray& data : data_) {
|
||||
AudioBus::Channel channel(data);
|
||||
|
||||
// Fill each channel with a different value.
|
||||
std::ranges::fill(channel, value++);
|
||||
@ -226,8 +237,8 @@ TEST_F(AudioBusTest, AllChannelsSubspan) {
|
||||
bus->set_frames(kFrameCount);
|
||||
AudioBus::ChannelVector channels;
|
||||
int value = 1;
|
||||
for (float* data : data_) {
|
||||
AudioBus::Channel channel(data, static_cast<size_t>(kFrameCount));
|
||||
for (AlignedFloatArray& data : data_) {
|
||||
AudioBus::Channel channel(data);
|
||||
|
||||
// Fill each sample with a different value.
|
||||
for (float& sample : channel) {
|
||||
@ -254,13 +265,17 @@ TEST_F(AudioBusTest, AllChannelsSubspan) {
|
||||
|
||||
// Verify an AudioBus created via wrapping a vector works as advertised.
|
||||
TEST_F(AudioBusTest, WrapVector) {
|
||||
data_.reserve(kChannels);
|
||||
for (int i = 0; i < kChannels; ++i) {
|
||||
data_.push_back(static_cast<float*>(base::AlignedAlloc(
|
||||
sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
|
||||
AllocateDataPerChannel();
|
||||
|
||||
std::vector<float*> data_pointers;
|
||||
data_pointers.reserve(kChannels);
|
||||
|
||||
for (AlignedFloatArray& data : data_) {
|
||||
data_pointers.push_back(data.as_span().data());
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_);
|
||||
std::unique_ptr<AudioBus> bus =
|
||||
AudioBus::WrapVector(kFrameCount, GetRawPointers(data_));
|
||||
VerifyChannelAndFrameCount(bus.get());
|
||||
VerifyReadWriteAndAlignment(bus.get());
|
||||
}
|
||||
@ -270,26 +285,29 @@ TEST_F(AudioBusTest, WrapMemory) {
|
||||
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
|
||||
ChannelLayoutConfig::FromLayout<kChannelLayout>(),
|
||||
kSampleRate, kFrameCount);
|
||||
size_t data_size = AudioBus::CalculateMemorySize(params);
|
||||
std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
|
||||
base::AlignedAlloc(data_size, AudioBus::kChannelAlignment)));
|
||||
size_t total_frame_count =
|
||||
AudioBus::CalculateMemorySize(params) / sizeof(float);
|
||||
AlignedFloatArray data = base::AlignedUninit<float>(total_frame_count);
|
||||
|
||||
// Fill the memory with a test value we can check for after wrapping.
|
||||
static const float kTestValue = 3;
|
||||
std::fill(data.get(), data.get() + data_size / sizeof(*data.get()),
|
||||
kTestValue);
|
||||
std::ranges::fill(data, kTestValue);
|
||||
|
||||
std::unique_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get());
|
||||
std::unique_ptr<AudioBus> bus =
|
||||
AudioBus::WrapMemory(params, data.as_span().data());
|
||||
// Verify the test value we filled prior to wrapping.
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kTestValue);
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
VerifySpanIsFilledWithValue(channel, kTestValue);
|
||||
}
|
||||
VerifyChannelAndFrameCount(bus.get());
|
||||
VerifyReadWriteAndAlignment(bus.get());
|
||||
|
||||
// Verify the channel vectors lie within the provided memory block.
|
||||
EXPECT_GE(bus->channel(0), data.get());
|
||||
EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(),
|
||||
data.get() + data_size / sizeof(*data.get()));
|
||||
const float* backing_memory_start = data.as_span().data();
|
||||
const float* backing_memory_end = backing_memory_start + total_frame_count;
|
||||
EXPECT_GE(bus->channel_span(0).data(), backing_memory_start);
|
||||
EXPECT_LT(bus->channel_span(bus->channels() - 1).data() + bus->frames(),
|
||||
backing_memory_end);
|
||||
}
|
||||
|
||||
// Simulate a shared memory transfer and verify results.
|
||||
@ -311,7 +329,7 @@ TEST_F(AudioBusTest, CopyTo) {
|
||||
// Try a copy to an AudioBus wrapping a vector.
|
||||
AllocateDataPerChannel();
|
||||
|
||||
bus2 = AudioBus::WrapVector(kFrameCount, data_);
|
||||
bus2 = AudioBus::WrapVector(kFrameCount, GetRawPointers(data_));
|
||||
CopyTest(bus1.get(), bus2.get());
|
||||
}
|
||||
{
|
||||
@ -331,50 +349,60 @@ TEST_F(AudioBusTest, Zero) {
|
||||
std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
|
||||
|
||||
// Fill the bus with dummy data.
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
|
||||
int value = 1;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
std::ranges::fill(channel, value++);
|
||||
}
|
||||
EXPECT_FALSE(bus->AreFramesZero());
|
||||
|
||||
// Zero first half the frames of each channel.
|
||||
bus->ZeroFrames(kFrameCount / 2);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
|
||||
value = 1;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
SCOPED_TRACE("First Half Zero");
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, 0);
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2,
|
||||
kFrameCount - kFrameCount / 2, i + 1);
|
||||
auto [first_half, second_half] = channel.split_at(kFrameCount / 2);
|
||||
VerifySpanIsFilledWithValue(first_half, 0);
|
||||
VerifySpanIsFilledWithValue(second_half, value++);
|
||||
}
|
||||
EXPECT_FALSE(bus->AreFramesZero());
|
||||
|
||||
// Fill the bus with dummy data.
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
|
||||
value = 1;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
std::ranges::fill(channel, value++);
|
||||
}
|
||||
|
||||
// Zero the last half of the frames.
|
||||
bus->ZeroFramesPartial(kFrameCount / 2, kFrameCount - kFrameCount / 2);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
static constexpr size_t kRemainingFrames = kFrameCount - kFrameCount / 2;
|
||||
bus->ZeroFramesPartial(kFrameCount / 2, kRemainingFrames);
|
||||
value = 1;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
SCOPED_TRACE("Last Half Zero");
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2,
|
||||
kFrameCount - kFrameCount / 2, 0);
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, i + 1);
|
||||
auto [first_half, second_half] = channel.split_at(kFrameCount / 2);
|
||||
VerifySpanIsFilledWithValue(first_half, value++);
|
||||
VerifySpanIsFilledWithValue(second_half, 0);
|
||||
}
|
||||
EXPECT_FALSE(bus->AreFramesZero());
|
||||
|
||||
// Fill the bus with dummy data.
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
|
||||
value = 1;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
std::ranges::fill(channel, value++);
|
||||
}
|
||||
|
||||
// Zero all the frames of each channel.
|
||||
bus->Zero();
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
SCOPED_TRACE("All Zero");
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0);
|
||||
VerifySpanIsFilledWithValue(channel, 0);
|
||||
}
|
||||
EXPECT_TRUE(bus->AreFramesZero());
|
||||
}
|
||||
|
||||
// Each test vector represents two channels of data in the following arbitrary
|
||||
// layout: <min, zero, max, min, max / 2, min / 2, zero, max, zero, zero>.
|
||||
static const int kTestVectorSize = 10;
|
||||
static constexpr int kTestVectorSize = 10;
|
||||
static const uint8_t kTestVectorUint8[kTestVectorSize] = {
|
||||
0, -INT8_MIN, UINT8_MAX,
|
||||
0, INT8_MAX / 2 + 128, INT8_MIN / 2 + 128,
|
||||
@ -407,7 +435,7 @@ static const float kTestVectorFloat32Sanitized[kTestVectorSize] = {
|
||||
-1.0f, 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 0.0f, 1.0f, -1.0f, -1.0f};
|
||||
|
||||
// Expected results.
|
||||
static const int kTestVectorFrameCount = kTestVectorSize / 2;
|
||||
static constexpr size_t kTestVectorFrameCount = kTestVectorSize / 2;
|
||||
static const float kTestVectorResult[][kTestVectorFrameCount] = {
|
||||
{-1.0f, 1.0f, 0.5f, 0.0f, 0.0f},
|
||||
{0.0f, -1.0f, -0.5f, 1.0f, 0.0f}};
|
||||
@ -420,8 +448,7 @@ TEST_F(AudioBusTest, FromInterleaved) {
|
||||
std::unique_ptr<AudioBus> expected =
|
||||
AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
|
||||
for (int ch = 0; ch < kTestVectorChannelCount; ++ch) {
|
||||
memcpy(expected->channel(ch), kTestVectorResult[ch],
|
||||
kTestVectorFrameCount * sizeof(*expected->channel(ch)));
|
||||
expected->channel_span(ch).copy_from(base::span(kTestVectorResult[ch]));
|
||||
}
|
||||
|
||||
{
|
||||
@ -465,8 +492,8 @@ TEST_F(AudioBusTest, FromInterleaved) {
|
||||
// Verify FromInterleavedPartial() deinterleaves audio correctly.
|
||||
TEST_F(AudioBusTest, FromInterleavedPartial) {
|
||||
// Only deinterleave the middle two frames in each channel.
|
||||
static const int kPartialStart = 1;
|
||||
static const int kPartialFrames = 2;
|
||||
static constexpr size_t kPartialStart = 1;
|
||||
static constexpr size_t kPartialFrames = 2;
|
||||
ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount);
|
||||
|
||||
std::unique_ptr<AudioBus> bus =
|
||||
@ -474,10 +501,11 @@ TEST_F(AudioBusTest, FromInterleavedPartial) {
|
||||
std::unique_ptr<AudioBus> expected =
|
||||
AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
|
||||
expected->Zero();
|
||||
for (int ch = 0; ch < kTestVectorChannelCount; ++ch) {
|
||||
memcpy(expected->channel(ch) + kPartialStart,
|
||||
kTestVectorResult[ch] + kPartialStart,
|
||||
kPartialFrames * sizeof(*expected->channel(ch)));
|
||||
int current_channel = 0;
|
||||
for (auto partial_channel :
|
||||
expected->AllChannelsSubspan(kPartialStart, kPartialFrames)) {
|
||||
partial_channel.copy_from(base::span(kTestVectorResult[current_channel++])
|
||||
.subspan(kPartialStart, kPartialFrames));
|
||||
}
|
||||
|
||||
{
|
||||
@ -496,8 +524,7 @@ TEST_F(AudioBusTest, ToInterleaved) {
|
||||
AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
|
||||
// Fill the bus with our test vector.
|
||||
for (int ch = 0; ch < bus->channels(); ++ch) {
|
||||
memcpy(bus->channel(ch), kTestVectorResult[ch],
|
||||
kTestVectorFrameCount * sizeof(*bus->channel(ch)));
|
||||
bus->channel_span(ch).copy_from(base::span(kTestVectorResult[ch]));
|
||||
}
|
||||
|
||||
{
|
||||
@ -548,7 +575,7 @@ TEST_F(AudioBusTest, ToInterleavedSanitized) {
|
||||
bus->FromInterleaved<Float32SampleTypeTraits>(kTestVectorFloat32Invalid,
|
||||
bus->frames());
|
||||
// Verify FromInterleaved applied no sanity.
|
||||
ASSERT_EQ(bus->channel(0)[0], kTestVectorFloat32Invalid[0]);
|
||||
ASSERT_EQ(bus->channel_span(0)[0], kTestVectorFloat32Invalid[0]);
|
||||
float test_array[std::size(kTestVectorFloat32Sanitized)];
|
||||
bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array);
|
||||
for (size_t i = 0; i < std::size(kTestVectorFloat32Sanitized); ++i)
|
||||
@ -576,7 +603,7 @@ TEST_F(AudioBusTest, CopyAndClipTo) {
|
||||
kTestVectorFloat32Sanitized, bus->frames());
|
||||
|
||||
// Verify FromInterleaved applied no sanity.
|
||||
ASSERT_EQ(bus->channel(0)[0], kTestVectorFloat32Invalid[0]);
|
||||
ASSERT_EQ(bus->channel_span(0)[0], kTestVectorFloat32Invalid[0]);
|
||||
|
||||
std::unique_ptr<AudioBus> copy_to_bus =
|
||||
AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
|
||||
@ -584,7 +611,8 @@ TEST_F(AudioBusTest, CopyAndClipTo) {
|
||||
|
||||
for (int ch = 0; ch < expected->channels(); ++ch) {
|
||||
for (int i = 0; i < expected->frames(); ++i)
|
||||
ASSERT_EQ(copy_to_bus->channel(ch)[i], expected->channel(ch)[i]);
|
||||
ASSERT_EQ(copy_to_bus->channel_span(ch)[i],
|
||||
expected->channel_span(ch)[i]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(expected->channels(), copy_to_bus->channels());
|
||||
@ -596,15 +624,14 @@ TEST_F(AudioBusTest, CopyAndClipTo) {
|
||||
// Verify ToInterleavedPartial() interleaves audio correctly.
|
||||
TEST_F(AudioBusTest, ToInterleavedPartial) {
|
||||
// Only interleave the middle two frames in each channel.
|
||||
static const int kPartialStart = 1;
|
||||
static const int kPartialFrames = 2;
|
||||
static constexpr size_t kPartialStart = 1;
|
||||
static constexpr size_t kPartialFrames = 2;
|
||||
ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount);
|
||||
|
||||
std::unique_ptr<AudioBus> expected =
|
||||
AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
|
||||
for (int ch = 0; ch < kTestVectorChannelCount; ++ch) {
|
||||
memcpy(expected->channel(ch), kTestVectorResult[ch],
|
||||
kTestVectorFrameCount * sizeof(*expected->channel(ch)));
|
||||
expected->channel_span(ch).copy_from(base::span(kTestVectorResult[ch]));
|
||||
}
|
||||
|
||||
{
|
||||
@ -631,11 +658,10 @@ struct ZeroingOutTestData {
|
||||
// Create a bus and fill each channel with a test pattern of form
|
||||
// [1.0, 2.0, 3.0, ...]
|
||||
bus_under_test = AudioBus::Create(kChannelCount, kFrameCount);
|
||||
for (int ch = 0; ch < kChannelCount; ++ch) {
|
||||
auto* sample_array_for_current_channel = bus_under_test->channel(ch);
|
||||
for (int frame_index = 0; frame_index < kFrameCount; frame_index++) {
|
||||
sample_array_for_current_channel[frame_index] =
|
||||
static_cast<float>(frame_index + 1);
|
||||
for (auto channel : bus_under_test->AllChannels()) {
|
||||
int value = 1;
|
||||
for (float& sample : channel) {
|
||||
sample = value++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -654,13 +680,14 @@ TEST_F(AudioBusTest, FromInterleavedZerosOutUntouchedFrames) {
|
||||
test_data.bus_under_test->FromInterleaved<Float32SampleTypeTraits>(
|
||||
&test_data.interleaved_dummy_frames[0], test_data.kInterleavedFrameCount);
|
||||
|
||||
const size_t untouched_frame_count =
|
||||
test_data.kFrameCount - test_data.kInterleavedFrameCount;
|
||||
|
||||
// Verification
|
||||
for (int ch = 0; ch < test_data.kChannelCount; ++ch) {
|
||||
auto* sample_array_for_current_channel =
|
||||
test_data.bus_under_test->channel(ch);
|
||||
for (int frame_index = test_data.kInterleavedFrameCount;
|
||||
frame_index < test_data.kFrameCount; frame_index++) {
|
||||
ASSERT_EQ(0.0f, sample_array_for_current_channel[frame_index]);
|
||||
for (auto partial_channel : test_data.bus_under_test->AllChannelsSubspan(
|
||||
test_data.kInterleavedFrameCount, untouched_frame_count)) {
|
||||
for (auto sample : partial_channel) {
|
||||
ASSERT_EQ(0.0f, sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -679,8 +706,8 @@ TEST_F(AudioBusTest, FromInterleavedPartialDoesNotZeroOutUntouchedFrames) {
|
||||
|
||||
// Verification
|
||||
for (int ch = 0; ch < test_data.kChannelCount; ++ch) {
|
||||
auto* sample_array_for_current_channel =
|
||||
test_data.bus_under_test->channel(ch);
|
||||
auto sample_array_for_current_channel =
|
||||
test_data.bus_under_test->channel_span(ch);
|
||||
for (int frame_index =
|
||||
test_data.kInterleavedFrameCount + kWriteOffsetInFrames;
|
||||
frame_index < test_data.kFrameCount; frame_index++) {
|
||||
@ -702,8 +729,8 @@ TEST_F(AudioBusTest, FromInterleavedPartialDoesNotZeroOutUntouchedFrames) {
|
||||
|
||||
// Verification
|
||||
for (int ch = 0; ch < test_data.kChannelCount; ++ch) {
|
||||
auto* sample_array_for_current_channel =
|
||||
test_data.bus_under_test->channel(ch);
|
||||
auto sample_array_for_current_channel =
|
||||
test_data.bus_under_test->channel_span(ch);
|
||||
// Check untouched frames before write offset
|
||||
for (int frame_index = 0; frame_index < kWriteOffsetInFrames;
|
||||
frame_index++) {
|
||||
@ -725,31 +752,31 @@ TEST_F(AudioBusTest, Scale) {
|
||||
std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
|
||||
|
||||
// Fill the bus with dummy data.
|
||||
static const float kFillValue = 1;
|
||||
for (int i = 0; i < bus->channels(); ++i)
|
||||
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), kFillValue);
|
||||
static constexpr float kFillValue = 1;
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
std::ranges::fill(channel, kFillValue);
|
||||
}
|
||||
|
||||
// Adjust by an invalid volume and ensure volume is unchanged.
|
||||
bus->Scale(-1);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
SCOPED_TRACE("Invalid Scale");
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kFillValue);
|
||||
VerifySpanIsFilledWithValue(channel, kFillValue);
|
||||
}
|
||||
|
||||
// Verify correct volume adjustment.
|
||||
static const float kVolume = 0.5;
|
||||
static constexpr float kVolume = 0.5;
|
||||
bus->Scale(kVolume);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
SCOPED_TRACE("Half Scale");
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(),
|
||||
kFillValue * kVolume);
|
||||
VerifySpanIsFilledWithValue(channel, kFillValue * kVolume);
|
||||
}
|
||||
|
||||
// Verify zero volume case.
|
||||
bus->Scale(0);
|
||||
for (int i = 0; i < bus->channels(); ++i) {
|
||||
for (auto channel : bus->AllChannels()) {
|
||||
SCOPED_TRACE("Zero Scale");
|
||||
VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0);
|
||||
VerifySpanIsFilledWithValue(channel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -767,7 +794,7 @@ TEST_F(AudioBusTest, Bitstream) {
|
||||
|
||||
EXPECT_EQ(0, bus->GetBitstreamFrames());
|
||||
bus->SetBitstreamFrames(kFrameCount);
|
||||
EXPECT_EQ(kFrameCount, bus->GetBitstreamFrames());
|
||||
EXPECT_EQ(static_cast<int>(kFrameCount), bus->GetBitstreamFrames());
|
||||
|
||||
std::unique_ptr<AudioBus> bus2 = AudioBus::Create(1, kFrameCount);
|
||||
CopyTest(bus.get(), bus2.get());
|
||||
|
Reference in New Issue
Block a user